From 5c42690586b915abee63c586d66929da75e54c4b Mon Sep 17 00:00:00 2001 From: Kuingsmile Date: Wed, 5 Mar 2025 13:19:03 +0800 Subject: [PATCH 01/22] :package: Chore(custom): update scripts --- scripts/check-dep.js | 4 +- scripts/config.js | 96 +++++++++++++++------------- scripts/gen-i18n-types.js | 3 +- scripts/gen-sha256.js | 130 ++++++++++++++++++++++++++++++-------- scripts/notarize.js | 9 +-- scripts/upload-beta.js | 2 +- 6 files changed, 163 insertions(+), 81 deletions(-) diff --git a/scripts/check-dep.js b/scripts/check-dep.js index a855d203..ba21d407 100644 --- a/scripts/check-dep.js +++ b/scripts/check-dep.js @@ -1,7 +1,7 @@ const ncu = require('npm-check-updates') const axios = require('axios') -async function getRepositoryInfo (packageName) { +async function getRepositoryInfo(packageName) { try { const { data } = await axios.get(`https://registry.npmjs.org/${packageName}`) const repository = data.repository @@ -17,7 +17,7 @@ async function getRepositoryInfo (packageName) { return null } -async function checkUpdates () { +async function checkUpdates() { const updated = await ncu.run({ packageFile: './package.json', upgrade: false diff --git a/scripts/config.js b/scripts/config.js index 83183636..358adccb 100644 --- a/scripts/config.js +++ b/scripts/config.js @@ -1,53 +1,63 @@ // different platform has different format // macos -const darwin = [{ - appNameWithPrefix: 'PicList-', - ext: '.dmg', - arch: '-arm64', - 'version-file': 'latest-mac.yml' -}, { - appNameWithPrefix: 'PicList-', - ext: '.dmg', - arch: '-x64', - 'version-file': 'latest-mac.yml' -}, { - appNameWithPrefix: 'PicList-', - ext: '.dmg', - arch: '-universal', - 'version-file': 'latest-mac.yml' -} +const darwin = [ + { + appNameWithPrefix: 'PicList-', + ext: '.dmg', + arch: '-arm64', + 'version-file': 'latest-mac.yml' + }, + { + appNameWithPrefix: 'PicList-', + ext: '.dmg', + arch: '-x64', + 'version-file': 'latest-mac.yml' + }, + { + appNameWithPrefix: 'PicList-', + ext: '.dmg', + arch: '-universal', + 'version-file': 'latest-mac.yml' + } ] -const linux = [{ - appNameWithPrefix: 'PicList-', - ext: '.AppImage', - arch: '', - 'version-file': 'latest-linux.yml' -}, { - appNameWithPrefix: 'piclist_', - ext: '.snap', - arch: '_amd64', - 'version-file': 'latest-linux.yml' -}] +const linux = [ + { + appNameWithPrefix: 'PicList-', + ext: '.AppImage', + arch: '', + 'version-file': 'latest-linux.yml' + }, + { + appNameWithPrefix: 'piclist_', + ext: '.snap', + arch: '_amd64', + 'version-file': 'latest-linux.yml' + } +] // windows -const win32 = [{ - appNameWithPrefix: 'PicList-Setup-', - ext: '.exe', - arch: '-ia32', - 'version-file': 'latest.yml' -}, { - appNameWithPrefix: 'PicList-Setup-', - ext: '.exe', - arch: '-x64', - 'version-file': 'latest.yml' -}, { - appNameWithPrefix: 'PicList-Setup-', - ext: '.exe', - arch: '', // 32 & 64 - 'version-file': 'latest.yml' -}] +const win32 = [ + { + appNameWithPrefix: 'PicList-Setup-', + ext: '.exe', + arch: '-ia32', + 'version-file': 'latest.yml' + }, + { + appNameWithPrefix: 'PicList-Setup-', + ext: '.exe', + arch: '-x64', + 'version-file': 'latest.yml' + }, + { + appNameWithPrefix: 'PicList-Setup-', + ext: '.exe', + arch: '', // 32 & 64 + 'version-file': 'latest.yml' + } +] module.exports = { darwin, diff --git a/scripts/gen-i18n-types.js b/scripts/gen-i18n-types.js index 3f156262..d0e29b14 100644 --- a/scripts/gen-i18n-types.js +++ b/scripts/gen-i18n-types.js @@ -12,8 +12,7 @@ const obj = yaml.load(langFile) const keys = Object.keys(obj) -const types = -`interface ILocales { +const types = `interface ILocales { ${keys.map(key => `${key}: string`).join('\n ')} } type ILocalesKey = keyof ILocales diff --git a/scripts/gen-sha256.js b/scripts/gen-sha256.js index 7ebaae64..3cb7cdb0 100644 --- a/scripts/gen-sha256.js +++ b/scripts/gen-sha256.js @@ -4,55 +4,133 @@ const path = require('path') const axios = require('axios') const fs = require('fs-extra') const pkg = require('../package.json') -const version = pkg.version +const version = process.argv[2] || pkg.version -const x64URL = `https://release.piclist.cn/latest/PicList-${version}-x64.dmg` -const arm64URL = `https://release.piclist.cn/latest/PicList-${version}-arm64.dmg` -const x64Path = path.join(os.homedir(), 'Downloads', 'PicList-x64.dmg') -const arm64Path = path.join(os.homedir(), 'Downloads', 'PicList-arm64.dmg') +// Configuration +const BASE_URL = `https://github.com/Kuingsmile/PicList/releases/download/v${version}` +const DOWNLOAD_DIR = process.argv[3] || path.join(os.homedir(), 'Downloads') +// File information +const files = [ + { + name: 'PicList-x64.dmg', + url: `${BASE_URL}/PicList-${version}-x64.dmg` + }, + { + name: 'PicList-arm64.dmg', + url: `${BASE_URL}/PicList-${version}-arm64.dmg` + } +] + +/** + * Create progress bar string + */ +function getProgressBar(current, total, length = 20) { + const progress = Math.round((current / total) * length) + const percentage = Math.round((current / total) * 100) + const bar = '█'.repeat(progress) + '░'.repeat(length - progress) + return `[${bar}] ${percentage}% (${formatBytes(current)}/${formatBytes(total)})` +} + +/** + * Format bytes to human-readable format + */ +function formatBytes(bytes, decimals = 2) { + if (bytes === 0) return '0 Bytes' + const k = 1024 + const sizes = ['Bytes', 'KB', 'MB', 'GB'] + const i = Math.floor(Math.log(bytes) / Math.log(k)) + return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i] +} + +/** + * Download file and calculate SHA256 hash + */ +async function downloadAndHash(fileInfo) { + const { url, name } = fileInfo + const filePath = path.join(DOWNLOAD_DIR, name) + + console.log(`\nStarting download: ${name} from ${url}`) -const downloadAndHash = async (url, path) => { try { const response = await axios({ method: 'get', url, responseType: 'stream' }) - const writer = fs.createWriteStream(path) + + const writer = fs.createWriteStream(filePath) response.data.pipe(writer) const hash = crypto.createHash('sha256') const progressTotal = parseInt(response.headers['content-length'], 10) let progressCurrent = 0 - console.log('\n') - response.data.on('data', (chunk) => { + response.data.on('data', chunk => { hash.update(chunk) progressCurrent += chunk.length - const progressBar = Math.round(progressCurrent / progressTotal * 100) - process.stdout.write(`\r${progressBar}% ${path}`) + process.stdout.write(`\r${name}: ${getProgressBar(progressCurrent, progressTotal)}`) }) await new Promise((resolve, reject) => { - response.data.on('end', () => { - resolve() - }) - response.data.on('error', (err) => { - reject(err) - }) + writer.on('finish', resolve) + writer.on('error', reject) + response.data.on('error', reject) }) - console.log(`\n${path} SHA256: ${hash.digest('hex')}`) + const hashValue = hash.digest('hex') + console.log(`\n✅ ${name} SHA256: ${hashValue}`) - await fs.remove(path) - console.log(`Deleted ${path}`) + // Write hash to a file for reference + await fs.writeFile(`${filePath}.sha256`, hashValue) + console.log(`Hash saved to ${filePath}.sha256`) + + if (process.argv.includes('--keep-files')) { + console.log(`Keeping file: ${filePath}`) + } else { + await fs.remove(filePath) + console.log(`Deleted: ${filePath}`) + } + + return { name, hash: hashValue } } catch (err) { - console.error(`\nError downloading ${url}: ${err.message}`) + console.error(`\n❌ Error processing ${name}: ${err.message}`) + throw err } } -downloadAndHash(x64URL, x64Path).then(() => { - downloadAndHash(arm64URL, arm64Path) -}).catch(() => { - downloadAndHash(arm64URL, arm64Path) -}) +/** + * Main function + */ +async function main() { + console.log(`Generating SHA256 hashes for PicList v${version}`) + console.log(`Download directory: ${DOWNLOAD_DIR}`) + + try { + // Ensure download directory exists + await fs.ensureDir(DOWNLOAD_DIR) + + // Start all downloads concurrently + const results = await Promise.allSettled(files.map(downloadAndHash)) + + // Output summary + console.log('\n===== SUMMARY =====') + results.forEach((result, index) => { + const fileName = files[index].name + if (result.status === 'fulfilled') { + console.log(`✅ ${fileName}: ${result.value.hash}`) + } else { + console.log(`❌ ${fileName}: Failed - ${result.reason.message}`) + } + }) + + // Check if all downloads were successful + if (results.some(r => r.status === 'rejected')) { + process.exit(1) + } + } catch (err) { + console.error(`\nCritical error: ${err.message}`) + process.exit(1) + } +} + +main() diff --git a/scripts/notarize.js b/scripts/notarize.js index 3aebfb25..3435af2a 100644 --- a/scripts/notarize.js +++ b/scripts/notarize.js @@ -3,14 +3,9 @@ require('dotenv').config() const { notarize } = require('@electron/notarize') -const { - ELECTRON_SKIP_NOTARIZATION, - XCODE_APP_LOADER_EMAIL, - XCODE_APP_LOADER_PASSWORD, - XCODE_TEAM_ID -} = process.env +const { ELECTRON_SKIP_NOTARIZATION, XCODE_APP_LOADER_EMAIL, XCODE_APP_LOADER_PASSWORD, XCODE_TEAM_ID } = process.env -async function main (context) { +async function main(context) { const { electronPlatformName, appOutDir } = context if ( diff --git a/scripts/upload-beta.js b/scripts/upload-beta.js index 86402d10..203fe3de 100644 --- a/scripts/upload-beta.js +++ b/scripts/upload-beta.js @@ -45,7 +45,7 @@ const uploadFile = async () => { } } }) - parallelUploads3.on('httpUploadProgress', (progress) => { + parallelUploads3.on('httpUploadProgress', progress => { const progressBar = Math.round((progress.loaded / progress.total) * 100) process.stdout.write(`\r${progressBar}% ${fileName}`) }) From 89f8d4c2d593cd91c96bbfe1ac058200ee1597a4 Mon Sep 17 00:00:00 2001 From: Kuingsmile Date: Wed, 9 Apr 2025 11:49:18 +0800 Subject: [PATCH 02/22] :sparkles: Feature(custom): enhance upload page UI and functionality --- public/i18n/en.yml | 1 + public/i18n/zh-CN.yml | 3 +- public/i18n/zh-TW.yml | 3 +- .../components/ImageProcessSetting.vue | 607 ++++++++++++---- src/renderer/pages/Upload.vue | 663 +++++++++++++----- src/universal/types/i18n.d.ts | 1 + 6 files changed, 975 insertions(+), 303 deletions(-) diff --git a/public/i18n/en.yml b/public/i18n/en.yml index c8fe6a00..286e0d08 100644 --- a/public/i18n/en.yml +++ b/public/i18n/en.yml @@ -125,6 +125,7 @@ UPLOAD_PAGE_IMAGE_PROCESS_QUALITY: Compression Quality(1-100) UPLOAD_PAGE_IMAGE_PROCESS_ISCONVERT: Convert Format UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT: Destination Format UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT_SPECIFIC: 'Specific Format, Please enter in json format, e.g. {"png": "jpg"}' +UPLOAD_PAGE_IMAGE_PROCESS_TRANSFORMATION: Image Rotate Setting UPLOAD_PAGE_IMAGE_PROCESS_ISFLIP: Whether to flip vertically UPLOAD_PAGE_IMAGE_PROCESS_ISFLOP: Whether to flip horizontally UPLOAD_PAGE_IMAGE_PROCESS_ISRESIZE: Resize to fixed size diff --git a/public/i18n/zh-CN.yml b/public/i18n/zh-CN.yml index 912a8987..c9d850ba 100644 --- a/public/i18n/zh-CN.yml +++ b/public/i18n/zh-CN.yml @@ -125,6 +125,7 @@ UPLOAD_PAGE_IMAGE_PROCESS_QUALITY: 压缩质量(1-100) UPLOAD_PAGE_IMAGE_PROCESS_ISCONVERT: 是否转换格式 UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT: 转换目的格式 UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT_SPECIFIC: '精细化转换格式, 请输入JSON格式,如: {"png": "jpg"}' +UPLOAD_PAGE_IMAGE_PROCESS_TRANSFORMATION: 图片旋转设置 UPLOAD_PAGE_IMAGE_PROCESS_ISFLIP: 是否进行垂直翻转 UPLOAD_PAGE_IMAGE_PROCESS_ISFLOP: 是否进行水平翻转 UPLOAD_PAGE_IMAGE_PROCESS_ISRESIZE: 是否按固定尺寸调整图片 @@ -350,7 +351,7 @@ DRAG_FILE_TO_HERE: 将文件拖拽到此处,或 CLICK_TO_UPLOAD: 点击上传 LINK_FORMAT: 链接格式 CUSTOM: 自定义 -CLIPBOARD_PICTURE: 剪贴板图片 +CLIPBOARD_PICTURE: 剪贴板 TIPS_DRAG_VALID_PICTURE_OR_URL: 请拖入合法的图片文件或者图片URL地址 TIPS_INPUT_URL: 请输入URL TIPS_HTTP_PREFIX: http://或者https://开头 diff --git a/public/i18n/zh-TW.yml b/public/i18n/zh-TW.yml index c22910b9..dc04c653 100644 --- a/public/i18n/zh-TW.yml +++ b/public/i18n/zh-TW.yml @@ -125,6 +125,7 @@ UPLOAD_PAGE_IMAGE_PROCESS_QUALITY: 壓縮質量(1-100) UPLOAD_PAGE_IMAGE_PROCESS_ISCONVERT: 是否轉換格式 UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT: 轉換目的格式 UPLOAD_PAGE_IMAGE_PROCESS_CONVERTFORMAT_SPECIFIC: '指定格式, 请输入JSON格式配置,如{"jpg":"png"}' +UPLOAD_PAGE_IMAGE_PROCESS_TRANSFORMATION: 圖片翻轉设置 UPLOAD_PAGE_IMAGE_PROCESS_ISFLIP: 是否進行垂直翻轉 UPLOAD_PAGE_IMAGE_PROCESS_ISFLOP: 是否進行水平翻轉 UPLOAD_PAGE_IMAGE_PROCESS_ISRESIZE: 是否按固定尺寸調整圖片 @@ -348,7 +349,7 @@ DRAG_FILE_TO_HERE: 將檔案拖曳到此處,或 CLICK_TO_UPLOAD: 點擊上傳 LINK_FORMAT: 連結格式 CUSTOM: 自訂 -CLIPBOARD_PICTURE: 剪貼簿圖片 +CLIPBOARD_PICTURE: 剪貼簿 TIPS_DRAG_VALID_PICTURE_OR_URL: 請拖入合法的圖片檔案或者圖片URL地址 TIPS_INPUT_URL: 請輸入URL TIPS_HTTP_PREFIX: http://或者https://開頭 diff --git a/src/renderer/components/ImageProcessSetting.vue b/src/renderer/components/ImageProcessSetting.vue index ab916f36..68ab957f 100644 --- a/src/renderer/components/ImageProcessSetting.vue +++ b/src/renderer/components/ImageProcessSetting.vue @@ -2,138 +2,281 @@ - - - - - - - {{ $T('UPLOAD_PAGE_IMAGE_PROCESS_WMTYPE_TEXT') }} - - - {{ $T('UPLOAD_PAGE_IMAGE_PROCESS_WMTYPE_IMAGE') }} - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{ item[1] }} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+ +
+ +
+
+ +

{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_ISADDWM') }}

+
+ +
+ + + {{ waterMarkForm.isAddWatermark ? $T('ENABLE') : $T('DISABLE') }} + + +
+ + + {{ $T('UPLOAD_PAGE_IMAGE_PROCESS_WMTYPE_TEXT') }} + {{ $T('UPLOAD_PAGE_IMAGE_PROCESS_WMTYPE_IMAGE') }} + + + + + + + + + + + {{ item[1] }} + + + + +
+ + + + + + + +
+ + +
+

{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_WMTYPE_TEXT') }}

+ + + + + + + + + +
+ + {{ waterMarkForm.watermarkColor }} +
+
+
+ + +
+

{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_WMTYPE_IMAGE') }}

+ + + +
+
+
+
+ + +
+
+ +

{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_ISCONVERT') }}

+
+ +
+ + + {{ compressForm.isConvert ? $T('ENABLE') : $T('DISABLE') }} + + +
+ + + + + + + + + +
+
+
+
+ + +
+ +
+
+ +

{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_QUALITY') }}

+
+ +
+ + + {{ $T('UPLOAD_PAGE_IMAGE_PROCESS_ISREMOVEEXIF') }} + + + + + +
+
+ + +
+
+ +

{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_ISRESIZE') }}

+
+ +
+ + + {{ compressForm.isReSize ? $T('ENABLE') : $T('DISABLE') }} + + +
+
+ + + + + + + +
+ + + + + + + + +
+
+
+ + +
+
+ +

{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_ISRESIZEBYPERCENT') }}

+
+ +
+ + + {{ compressForm.isReSizeByPercent ? $T('ENABLE') : $T('DISABLE') }} + + +
+ + + +
+
+
+ + +
+
+ +

{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_TRANSFORMATION') }}

+
+ +
+
+ + + {{ $T('UPLOAD_PAGE_IMAGE_PROCESS_ISFLIP') }} + + + + + {{ $T('UPLOAD_PAGE_IMAGE_PROCESS_ISFLOP') }} + +
+ + + + {{ + compressForm.isRotate + ? $T('UPLOAD_PAGE_IMAGE_PROCESS_ISROTATE') + : $T('UPLOAD_PAGE_IMAGE_PROCESS_ISROTATE') + }} + + +
+ +
+ +
+ + 90° + 180° + 270° +
+
+
+
+
+
+
+
+ + +
{{ $T('UPLOAD_PAGE_IMAGE_PROCESS_CONFIRM') }} {{ $T('UPLOAD_PAGE_IMAGE_PROCESS_CANCEL') }} - +
+ + diff --git a/src/renderer/pages/Upload.vue b/src/renderer/pages/Upload.vue index a34e0745..8bd4cb06 100644 --- a/src/renderer/pages/Upload.vue +++ b/src/renderer/pages/Upload.vue @@ -1,99 +1,108 @@