/* global wx */ /* eslint-disable no-console */ const { buildShareGridTileFileName, buildShareGridTilePlan, normalizeShareGridQuery, } = require('../host-bridge/shareGrid'); const WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE = '九宫切图保存失败。'; function logShareGridFailure(label, _error) { console.error(`[share-grid] ${label}`); } function rejectShareGridSaveFailure(reject, label, error) { logShareGridFailure(label, error); reject(new Error(WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE)); } function downloadImage(imageUrl) { return new Promise((resolve, reject) => { wx.downloadFile({ url: imageUrl, success(response) { if (response.statusCode >= 200 && response.statusCode < 300) { resolve(response.tempFilePath); return; } reject(new Error(`封面下载失败:${response.statusCode}`)); }, fail(error) { rejectShareGridSaveFailure(reject, 'download failed', error); }, }); }); } function getImageInfo(src) { return new Promise((resolve, reject) => { wx.getImageInfo({ src, success: resolve, fail(error) { rejectShareGridSaveFailure(reject, 'read image info failed', error); }, }); }); } function getCanvasNode(page) { return new Promise((resolve, reject) => { wx.createSelectorQuery() .in(page) .select('#share-grid-canvas') .fields({ node: true, size: true }) .exec((results) => { const canvas = results && results[0] && results[0].node; if (canvas) { resolve(canvas); return; } reject(new Error('切图画布初始化失败')); }); }); } function canvasToTempFilePath(canvas, width, height) { return new Promise((resolve, reject) => { wx.canvasToTempFilePath({ canvas, width, height, destWidth: width, destHeight: height, fileType: 'png', success(response) { resolve(response.tempFilePath); }, fail(error) { rejectShareGridSaveFailure(reject, 'export tile failed', error); }, }); }); } function saveImageToAlbum(filePath) { return new Promise((resolve, reject) => { wx.saveImageToPhotosAlbum({ filePath, success() { resolve(); }, fail(error) { rejectShareGridSaveFailure(reject, 'save album failed', error); }, }); }); } function copyTempFileWithName(tempFilePath, fileName) { const fileSystem = wx.getFileSystemManager && wx.getFileSystemManager(); const userDataPath = wx.env && wx.env.USER_DATA_PATH; if ( !fileSystem || !userDataPath || typeof fileSystem.copyFile !== 'function' ) { return Promise.resolve(tempFilePath); } const targetPath = `${userDataPath}/${fileName}`; return new Promise((resolve) => { fileSystem.copyFile({ srcPath: tempFilePath, destPath: targetPath, success() { resolve(targetPath); }, fail() { resolve(tempFilePath); }, }); }); } async function saveGridTiles(page, params, localImagePath, imageInfo) { const canvas = await getCanvasNode(page); const context = canvas.getContext('2d'); const image = canvas.createImage(); await new Promise((resolve, reject) => { image.onload = resolve; image.onerror = () => reject(new Error('封面绘制失败')); image.src = localImagePath; }); const plan = buildShareGridTilePlan(imageInfo.width, imageInfo.height); for (const tile of plan) { canvas.width = tile.sourceWidth; canvas.height = tile.sourceHeight; context.clearRect(0, 0, tile.sourceWidth, tile.sourceHeight); context.drawImage( image, tile.sourceX, tile.sourceY, tile.sourceWidth, tile.sourceHeight, 0, 0, tile.sourceWidth, tile.sourceHeight, ); const tempFilePath = await canvasToTempFilePath( canvas, tile.sourceWidth, tile.sourceHeight, ); const namedFilePath = await copyTempFileWithName( tempFilePath, buildShareGridTileFileName(params, tile.index), ); await saveImageToAlbum(namedFilePath); page.setData({ savedCount: tile.index + 1, }); } } function createWechatShareGridPage() { return { data: { errorMessage: '', loading: true, savedCount: 0, title: '九宫切图', }, async onLoad(query = {}) { const params = normalizeShareGridQuery(query); this._shareGridParams = params; this.setData({ errorMessage: '', loading: true, savedCount: 0, title: params.title, }); if (!params.imageUrl) { this.setData({ errorMessage: '缺少封面图。', loading: false, }); return; } try { const localImagePath = await downloadImage(params.imageUrl); const imageInfo = await getImageInfo(localImagePath); await saveGridTiles(this, params, localImagePath, imageInfo); this.setData({ loading: false, savedCount: 9, }); wx.showToast({ title: '已保存', icon: 'success', }); } catch (error) { logShareGridFailure('save failed', error); this.setData({ errorMessage: WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE, loading: false, }); } }, handleBack() { wx.navigateBack(); }, }; } module.exports = { WECHAT_SHARE_GRID_SAVE_UNAVAILABLE_MESSAGE, createWechatShareGridPage, };