diff --git a/build/buildUniversalPkg.js b/build/buildUniversalPkg.js new file mode 100644 index 0000000..3286686 --- /dev/null +++ b/build/buildUniversalPkg.js @@ -0,0 +1,10 @@ +const { makeUniversalApp } = require('@electron/universal'); + +const path = '/Users/bruce/Documents/repos/fluent-reader/bin/' + +makeUniversalApp({ + x64AppPath: path + '/darwin/x64/mas/Fluent Reader.app', + arm64AppPath: path + '/darwin/arm64/mas/Fluent Reader.app', + outAppPath: path + '/Fluent Reader.app', + force: true +}); diff --git a/build/resignAndPackage.sh b/build/resignAndPackage.sh index 874d62e..e71a15e 100644 --- a/build/resignAndPackage.sh +++ b/build/resignAndPackage.sh @@ -1,3 +1,5 @@ +#TODO: add "ElectronTeamIDEM8VE646TZ" to Info.plist + printf "......................\nresignAndPackage start\n\n" # Name of your app. @@ -5,9 +7,9 @@ APP="Fluent Reader" # Your Certificate name. CERT="Jieyu Yan (EM8VE646TZ)" # The path of your app to sign. -APP_PATH="/Users/bruce/Documents/repos/fluent-reader/bin/darwin/x64/mas/$APP.app" +APP_PATH="/Users/bruce/Documents/repos/fluent-reader/bin/$APP.app" # The path to the location you want to put the signed package. -RESULT_PATH="/Users/bruce/Documents/repos/fluent-reader/bin/darwin/x64/mas/$APP-mac_store.pkg" +RESULT_PATH="/Users/bruce/Documents/repos/fluent-reader/bin/$APP-mac_store.pkg" # The name of certificates you requested. APP_KEY="3rd Party Mac Developer Application: $CERT" INSTALLER_KEY="3rd Party Mac Developer Installer: $CERT" @@ -17,11 +19,22 @@ CHILD_PLIST="build/entitlements.mas.inherit.plist" LOGINHELPER_PLIST="build/entitlements.mas.loginhelper.plist" FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libEGL.dylib" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libGLESv2.dylib" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libswiftshader_libEGL.dylib" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libswiftshader_libGLESv2.dylib" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libvk_swiftshader.dylib" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Libraries/libffmpeg.dylib" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper (GPU).app/Contents/MacOS/$APP Helper (GPU)" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper (GPU).app/" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper (Renderer).app/Contents/MacOS/$APP Helper (Renderer)" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper (Renderer).app/" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper (Plugin).app/Contents/MacOS/$APP Helper (Plugin)" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper (Plugin).app/" codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/Contents/MacOS/$APP Login Helper" codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP" diff --git a/package-lock.json b/package-lock.json index 0b16223..817241d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "fluent-reader", - "version": "0.8.0", + "version": "0.8.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -46,6 +46,57 @@ "sumchecker": "^3.0.1" } }, + "@electron/universal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.4.tgz", + "integrity": "sha512-ajZoumi4XwqwmZe8YVhu4XGkZBCPyWZsVCQONPTIe9TUlleSN+dic3YpXlaWcilx/HOzTdldTKtabNTeI0gDoA==", + "dev": true, + "requires": { + "@malept/cross-spawn-promise": "^1.1.0", + "asar": "^3.0.3", + "debug": "^4.3.1", + "dir-compare": "^2.4.0", + "fs-extra": "^9.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "dev": true + } + } + }, "@fluentui/date-time-utilities": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-7.4.0.tgz", @@ -102,6 +153,58 @@ "tslib": "^1.10.0" } }, + "@malept/cross-spawn-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.0.tgz", + "integrity": "sha512-GeIK5rfU1Yd7BZJQPTGZMMmcZy5nhRToPXZcjaDwQDRSewdhp648GT2E4dh+L7+Io7AOW6WQ+GR44QSzja4qxg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "@microsoft/load-themed-styles": { "version": "1.10.66", "resolved": "https://registry.npmjs.org/@microsoft/load-themed-styles/-/load-themed-styles-1.10.66.tgz", @@ -150,6 +253,17 @@ "@types/node": "*" } }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "optional": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "@types/hoist-non-react-statics": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", @@ -172,6 +286,13 @@ "integrity": "sha512-LaMHENSO3MOcAgYD+iYsbuvEjDBQ0a5GmYyjca99MlHli0A5tcOTEy03UHiRk5cfubdPhVYCfCTXYN7/CLvnWA==", "dev": true }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true, + "optional": true + }, "@types/nedb": { "version": "1.8.9", "resolved": "https://registry.npmjs.org/@types/nedb/-/nedb-1.8.9.tgz", @@ -770,6 +891,27 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "asar": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.0.3.tgz", + "integrity": "sha512-k7zd+KoR+n8pl71PvgElcoKHrVNiSXtw7odKbyNpmgKe7EGRF9Pnu3uLOukD37EvavKwVFxOUpqXTIZC5B5Pmw==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "chromium-pickle-js": "^0.2.0", + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + } + } + }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -989,9 +1131,9 @@ "dev": true }, "boolean": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.1.tgz", - "integrity": "sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.2.tgz", + "integrity": "sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g==", "dev": true, "optional": true }, @@ -1249,6 +1391,12 @@ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -1818,9 +1966,9 @@ "dev": true }, "core-js": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.7.0.tgz", + "integrity": "sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==", "dev": true, "optional": true }, @@ -1961,12 +2109,12 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "decamelize": { @@ -2100,6 +2248,35 @@ } } }, + "dir-compare": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz", + "integrity": "sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA==", + "dev": true, + "requires": { + "buffer-equal": "1.0.0", + "colors": "1.0.3", + "commander": "2.9.0", + "minimatch": "3.0.4" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + } + } + }, "dmg-builder": { "version": "22.7.0", "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.7.0.tgz", @@ -2270,9 +2447,9 @@ } }, "electron": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-9.2.0.tgz", - "integrity": "sha512-4ecZ3rcGg//Gk4fAK3Jo61T+uh36JhU6HHR/PTujQqQiBw1g4tNPd4R2hGGth2d+7FkRIs5GdRNef7h64fQEMw==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/electron/-/electron-11.0.3.tgz", + "integrity": "sha512-nNfbLi7Q1xfJXOEO2adck5TS6asY4Jxc332E4Te8XfQ9hcaC3GiCdeEqk9FndNCwxhJA5Lr9jfSGRTwWebFa/w==", "dev": true, "requires": { "@electron/get": "^1.0.1", @@ -3431,6 +3608,12 @@ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, "hard-source-webpack-plugin": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.13.1.tgz", @@ -5633,13 +5816,13 @@ } }, "roarr": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.3.tgz", - "integrity": "sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA==", + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", "dev": true, "optional": true, "requires": { - "boolean": "^3.0.0", + "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", diff --git a/package.json b/package.json index 7b8edc7..324f5a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fluent-reader", - "version": "0.8.0", + "version": "0.8.1", "description": "Modern desktop RSS reader", "main": "./dist/electron.js", "scripts": { @@ -10,7 +10,9 @@ "package-win": "electron-builder -w --x64 && electron-builder -w --ia32 && electron-builder -w appx:arm64", "package-win-ci": "electron-builder -w --x64 -p never && electron-builder -w --ia32 -p never", "package-mac": "sudo electron-builder --mac", - "package-mas": "sudo electron-builder --mac mas && sudo bash build/resignAndPackage.sh", + "package-mas": "sudo CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --mac mas", + "package-mas-arm": "sudo CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --mac mas:arm64", + "package-mas-sign": "node build/buildUniversalPkg.js && sudo vim \"bin/Fluent Reader.app/Contents/Info.plist\" && sudo bash build/resignAndPackage.sh", "package-linux": "electron-builder --linux -p never" }, "keywords": [], @@ -45,7 +47,8 @@ "en-US", "fr-FR", "es", - "de" + "de", + "tr" ], "showNameOnTiles": true, "setBuildNumber": true @@ -67,7 +70,8 @@ "en", "fr", "es", - "de" + "de", + "tr" ] }, "mas": { @@ -86,6 +90,7 @@ } }, "devDependencies": { + "@electron/universal": "^1.0.4", "@fluentui/react": "^7.126.2", "@types/lovefield": "^2.1.3", "@types/nedb": "^1.8.9", @@ -93,7 +98,7 @@ "@types/react-dom": "^16.9.8", "@types/react-redux": "^7.1.9", "@yang991178/rss-parser": "^3.8.1", - "electron": "^9.2.0", + "electron": "^11.0.3", "electron-builder": "^22.7.0", "electron-react-devtools": "^0.5.3", "electron-store": "^5.2.0", diff --git a/src/components/menu.tsx b/src/components/menu.tsx index fc8444a..fd7df4e 100644 --- a/src/components/menu.tsx +++ b/src/components/menu.tsx @@ -25,14 +25,14 @@ export type MenuProps = { } export class Menu extends React.Component { - countOverflow = (count: number) => count >= 1000 ? "999+" : String(count) + countOverflow = (count: number) => count >= 1000 ? " 999+" : ` ${count}` getLinkGroups = (): INavLinkGroup[] => [ { links: [ { name: intl.get("search"), - ariaLabel: this.props.searchOn ? "✓" : "0", + ariaLabel: intl.get("search") + (this.props.searchOn ? " ✓" : " "), key: "search", icon: "Search", onClick: this.props.toggleSearch, @@ -40,7 +40,8 @@ export class Menu extends React.Component { }, { name: intl.get("allArticles"), - ariaLabel: this.countOverflow(Object.values(this.props.sources).map(s => s.unreadCount).reduce((a, b) => a + b, 0)), + ariaLabel: intl.get("allArticles") + + this.countOverflow(Object.values(this.props.sources).map(s => s.unreadCount).reduce((a, b) => a + b, 0)), key: ALL, icon: "TextDocument", onClick: () => this.props.allArticles(this.props.selected !== ALL), @@ -55,7 +56,7 @@ export class Menu extends React.Component { let sources = g.sids.map(sid => this.props.sources[sid]) return { name: g.name, - ariaLabel: this.countOverflow(sources.map(s => s.unreadCount).reduce((a, b) => a + b, 0)), + ariaLabel: g.name + this.countOverflow(sources.map(s => s.unreadCount).reduce((a, b) => a + b, 0)), key: "g-" + g.index, url: null, isExpanded: g.expanded, @@ -71,7 +72,7 @@ export class Menu extends React.Component { getSource = (s: RSSSource): INavLink => ({ name: s.name, - ariaLabel: this.countOverflow(s.unreadCount), + ariaLabel: s.name + this.countOverflow(s.unreadCount), key: "s-" + s.sid, onClick: () => this.props.selectSource(s), iconProps: s.iconurl ? this.getIconStyle(s.iconurl) : null, @@ -101,10 +102,11 @@ export class Menu extends React.Component { } _onRenderLink = (link: INavLink): JSX.Element => { + let count = link.ariaLabel.split(" ").pop() return ( this.onContext(link, event)}>
{link.name}
- {link.ariaLabel !== "0" &&
{link.ariaLabel}
} + {count && count !== "0" &&
{count}
}
) }; diff --git a/src/components/settings/app.tsx b/src/components/settings/app.tsx index 80f1281..e70bc7c 100644 --- a/src/components/settings/app.tsx +++ b/src/components/settings/app.tsx @@ -107,8 +107,8 @@ class AppTab extends React.Component { { key: "en-US", text: "English" }, { key: "es", text: "Español" }, { key: "fr-FR", text: "Français" }, + { key: "tr", text: "Türkçe" }, { key: "zh-CN", text: "中文(简体)" }, - { key: "tr", text: "Türkçe" }, ] toggleStatus = () => { diff --git a/src/scripts/models/feed.ts b/src/scripts/models/feed.ts index 762cfba..62a828b 100644 --- a/src/scripts/models/feed.ts +++ b/src/scripts/models/feed.ts @@ -1,7 +1,7 @@ import * as db from "../db" import lf from "lovefield" import { SourceActionTypes, INIT_SOURCES, ADD_SOURCE, DELETE_SOURCE } from "./source" -import { ItemActionTypes, FETCH_ITEMS, RSSItem, MARK_READ, MARK_UNREAD, TOGGLE_STARRED, TOGGLE_HIDDEN, applyItemReduction } from "./item" +import { ItemActionTypes, FETCH_ITEMS, RSSItem, TOGGLE_HIDDEN, applyItemReduction } from "./item" import { ActionStatus, AppThunk, mergeSortedArrays } from "../utils" import { PageActionTypes, SELECT_PAGE, PageType, APPLY_FILTER } from "./page" @@ -115,6 +115,7 @@ export type FeedState = { export const INIT_FEEDS = "INIT_FEEDS" export const INIT_FEED = "INIT_FEED" export const LOAD_MORE = "LOAD_MORE" +export const DISMISS_ITEMS = "DISMISS_ITEMS" interface initFeedsAction { type: typeof INIT_FEEDS @@ -137,7 +138,34 @@ interface loadMoreAction { err? } -export type FeedActionTypes = initFeedAction | initFeedsAction | loadMoreAction +interface dismissItemsAction{ + type: typeof DISMISS_ITEMS + fid: string + iids: Set +} + +export type FeedActionTypes = initFeedAction | initFeedsAction | loadMoreAction + | dismissItemsAction + +export function dismissItems(): AppThunk { + return (dispatch, getState) => { + const state = getState() + let fid = state.page.feedId + let filter = state.feeds[fid].filter + let iids = new Set() + for (let iid of state.feeds[fid].iids) { + let item = state.items[iid] + if (!FeedFilter.testItem(filter, item)) { + iids.add(iid) + } + } + dispatch({ + type: DISMISS_ITEMS, + fid: fid, + iids: iids + }) + } +} export function initFeedsRequest(): FeedActionTypes { return { @@ -293,6 +321,14 @@ export function feedReducer( } default: return state } + case DISMISS_ITEMS: + let nextState = { ...state } + let feed = state[action.fid] + nextState[action.fid] = { + ...feed, + iids: feed.iids.filter(iid => !action.iids.has(iid)) + } + return nextState case INIT_FEED: switch (action.status) { case ActionStatus.Success: return { diff --git a/src/scripts/models/item.ts b/src/scripts/models/item.ts index 581b208..7369041 100644 --- a/src/scripts/models/item.ts +++ b/src/scripts/models/item.ts @@ -3,7 +3,7 @@ import lf from "lovefield" import intl from "react-intl-universal" import { domParser, htmlDecode, ActionStatus, AppThunk, platformCtrl } from "../utils" import { RSSSource, updateSource, updateUnreadCounts } from "./source" -import { FeedActionTypes, INIT_FEED, LOAD_MORE, FilterType, initFeeds } from "./feed" +import { FeedActionTypes, INIT_FEED, LOAD_MORE, FilterType, initFeeds, dismissItems } from "./feed" import Parser from "@yang991178/rss-parser" import { pushNotification, setupAutoFetch, SettingsActionTypes, FREE_MEMORY } from "./app" import { getServiceHooks, syncWithService, ServiceActionTypes, SYNC_LOCAL_ITEMS } from "./service" @@ -213,6 +213,8 @@ export function fetchItems(background = false, sids: number[] = null): AppThunk< if (inserted.length > 0) { window.utils.requestAttention() } + } else { + dispatch(dismissItems()) } dispatch(setupAutoFetch()) })