mirror of
https://github.com/callumalpass/tasknotes.git
synced 2026-07-22 12:50:26 +00:00
Merge pull request #833 from callumalpass/release-notes
Add release notes viewer
This commit is contained in:
commit
85bcc4da82
24 changed files with 418 additions and 5 deletions
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
|
|
@ -71,7 +71,11 @@ jobs:
|
|||
- name: Run linter
|
||||
run: npm run lint || echo "Linting completed with warnings"
|
||||
timeout-minutes: 10
|
||||
|
||||
|
||||
- name: Generate release notes import
|
||||
run: node generate-release-notes-import.mjs
|
||||
timeout-minutes: 1
|
||||
|
||||
- name: Run type check
|
||||
run: npm run typecheck
|
||||
timeout-minutes: 5
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -16,6 +16,9 @@ main.js
|
|||
# It's built from source files in styles/ directory during CI/build process.
|
||||
styles.css
|
||||
|
||||
# Don't include the auto-generated release notes import file
|
||||
src/releaseNotes.ts
|
||||
|
||||
# Exclude sourcemaps
|
||||
*.map
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,17 @@ Example:
|
|||
|
||||
-->
|
||||
|
||||
## Added
|
||||
|
||||
- Added release notes viewer
|
||||
- New view displays release notes in a dedicated tab when plugin updates
|
||||
- Automatically opens after updating to a new version
|
||||
- Access anytime via command palette "TaskNotes: View release notes" or Settings > General
|
||||
- Release notes are rendered using native Obsidian markdown rendering
|
||||
- Includes link to view all releases on GitHub
|
||||
- Fully internationalized with i18n support
|
||||
- Auto-generation system ensures correct version is loaded without manual updates
|
||||
|
||||
## Fixed
|
||||
|
||||
- (#440) Fixed inline task replacement not working for links with relative paths
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import builtins from "builtin-modules";
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
const banner =
|
||||
`/*
|
||||
|
|
@ -11,6 +12,20 @@ if you want to view the source, please visit the github repository of this plugi
|
|||
|
||||
const prod = (process.argv[2] === "production");
|
||||
|
||||
// Plugin to import markdown files as strings
|
||||
const markdownPlugin = {
|
||||
name: 'markdown',
|
||||
setup(build) {
|
||||
build.onLoad({ filter: /\.md$/ }, async (args) => {
|
||||
const text = readFileSync(args.path, 'utf8');
|
||||
return {
|
||||
contents: `export default ${JSON.stringify(text)}`,
|
||||
loader: 'js',
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const context = await esbuild.context({
|
||||
banner: {
|
||||
js: banner,
|
||||
|
|
@ -39,6 +54,7 @@ const context = await esbuild.context({
|
|||
treeShaking: true,
|
||||
outfile: "main.js",
|
||||
minify: prod,
|
||||
plugins: [markdownPlugin],
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
|
|
|
|||
20
generate-release-notes-import.mjs
Normal file
20
generate-release-notes-import.mjs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { readFileSync, writeFileSync } from "fs";
|
||||
|
||||
// Read current version from manifest.json
|
||||
const manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
|
||||
const version = manifest.version;
|
||||
|
||||
// Generate the TypeScript file that imports the current version's release notes
|
||||
const content = `// Auto-generated file - do not edit manually
|
||||
// This file is regenerated during the build process to import the current version's release notes
|
||||
|
||||
import releaseNotes from "../docs/releases/${version}.md";
|
||||
|
||||
export const CURRENT_VERSION = "${version}";
|
||||
export const CURRENT_RELEASE_NOTES = releaseNotes;
|
||||
`;
|
||||
|
||||
// Write to src/releaseNotes.ts
|
||||
writeFileSync("src/releaseNotes.ts", content);
|
||||
|
||||
console.log(`✓ Generated release notes import for version ${version}`);
|
||||
|
|
@ -127,6 +127,10 @@
|
|||
"views.stats.sections.projectBreakdown": "c856b0f89a0d1f51f02f82726206cb07cd1ae95e",
|
||||
"views.stats.sections.dateRange": "6bb4b674b3232e32feb264e11f19ee1dbed354a3",
|
||||
"views.stats.filters.minTime": "77f4b7a081b20f78557dd404e14d91b89b52a27c",
|
||||
"views.releaseNotes.title": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"views.releaseNotes.header": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"views.releaseNotes.viewAllLink": "b37e5d2fb2faa630817557713df6363f4bd0f5cc",
|
||||
"views.releaseNotes.starMessage": "de98980ccdae9c93e30d1172d4c15c059ea0508c",
|
||||
"settings.tabs.general": "9239ee2cda84eca4c3440e2a7b50148af67da3d4",
|
||||
"settings.tabs.taskProperties": "770bd2ee4e0a455df6d1332def9c6c58f44994bc",
|
||||
"settings.tabs.defaults": "809ab386aa1c870ee286190b1af3eace7f0bfe30",
|
||||
|
|
@ -845,6 +849,7 @@
|
|||
"commands.pauseResumePomodoro": "1ac6f3fd60f918b25cfb95be70b9d43f3b3281bb",
|
||||
"commands.refreshCache": "0b56ae2b187bdf931d24258272f284d7046ad543",
|
||||
"commands.exportAllTasksIcs": "3f3714587b4802efeb6baf380a59615b8faf0c10",
|
||||
"commands.viewReleaseNotes": "04c2072af97cf70c22fbf9efa9b62eb2574d23d6",
|
||||
"modals.task.titlePlaceholder": "c8196f1d1039c2fb290add52ee990c571173d6f1",
|
||||
"modals.task.titleLabel": "768e0c1c69573fb588f61f1308a015c11468e05f",
|
||||
"modals.task.titleDetailedPlaceholder": "da3700738242c039de32d3f5e3a0ba10bc28ba0b",
|
||||
|
|
|
|||
120
i18n.state.json
120
i18n.state.json
|
|
@ -512,6 +512,22 @@
|
|||
"source": "77f4b7a081b20f78557dd404e14d91b89b52a27c",
|
||||
"translation": "a6bce6cf45ab6987a0491268052e0770559f80a4"
|
||||
},
|
||||
"views.releaseNotes.title": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "13e0a79179479dd7bd03740e53af56d3b965f8fc"
|
||||
},
|
||||
"views.releaseNotes.header": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "13e0a79179479dd7bd03740e53af56d3b965f8fc"
|
||||
},
|
||||
"views.releaseNotes.viewAllLink": {
|
||||
"source": "b37e5d2fb2faa630817557713df6363f4bd0f5cc",
|
||||
"translation": "beead282ed357e1ec1e06f7d34a3e9dfe3309181"
|
||||
},
|
||||
"views.releaseNotes.starMessage": {
|
||||
"source": "de98980ccdae9c93e30d1172d4c15c059ea0508c",
|
||||
"translation": "3886f7795b91fd4ed8d6fcdf37424e5e0b59857d"
|
||||
},
|
||||
"settings.tabs.general": {
|
||||
"source": "9239ee2cda84eca4c3440e2a7b50148af67da3d4",
|
||||
"translation": "21a7b4ecae6d99d7c9ae0fe00f0cc0a33f1e2b6f"
|
||||
|
|
@ -3372,6 +3388,10 @@
|
|||
"source": "3f3714587b4802efeb6baf380a59615b8faf0c10",
|
||||
"translation": "2b3a3551e913a0618f09a1378c63fa6b832fe6cf"
|
||||
},
|
||||
"commands.viewReleaseNotes": {
|
||||
"source": "04c2072af97cf70c22fbf9efa9b62eb2574d23d6",
|
||||
"translation": "d69d1c26f388903bba0094ba00f61217c47fa732"
|
||||
},
|
||||
"modals.task.titlePlaceholder": {
|
||||
"source": "c8196f1d1039c2fb290add52ee990c571173d6f1",
|
||||
"translation": "03f97eff6f24910100617f3fcbc4665e2e65cd7e"
|
||||
|
|
@ -6042,6 +6062,22 @@
|
|||
"source": "77f4b7a081b20f78557dd404e14d91b89b52a27c",
|
||||
"translation": "01c1479a894b4e8a3b6e679bd3630c1389c7cd60"
|
||||
},
|
||||
"views.releaseNotes.title": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "d77248708380c01950bad45e2eee3593861fe33c"
|
||||
},
|
||||
"views.releaseNotes.header": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "d77248708380c01950bad45e2eee3593861fe33c"
|
||||
},
|
||||
"views.releaseNotes.viewAllLink": {
|
||||
"source": "b37e5d2fb2faa630817557713df6363f4bd0f5cc",
|
||||
"translation": "5411820364300214189c01bbd57acdd6e8ac0a04"
|
||||
},
|
||||
"views.releaseNotes.starMessage": {
|
||||
"source": "de98980ccdae9c93e30d1172d4c15c059ea0508c",
|
||||
"translation": "f41b51d65c2637f895c175954e78a9c70d470034"
|
||||
},
|
||||
"settings.tabs.general": {
|
||||
"source": "9239ee2cda84eca4c3440e2a7b50148af67da3d4",
|
||||
"translation": "9239ee2cda84eca4c3440e2a7b50148af67da3d4"
|
||||
|
|
@ -8902,6 +8938,10 @@
|
|||
"source": "3f3714587b4802efeb6baf380a59615b8faf0c10",
|
||||
"translation": "8f93640a115b91031d8f53e89543cc0bf04e300b"
|
||||
},
|
||||
"commands.viewReleaseNotes": {
|
||||
"source": "04c2072af97cf70c22fbf9efa9b62eb2574d23d6",
|
||||
"translation": "6b3d99d1c66a1ab48efa9303a68404ff95c10897"
|
||||
},
|
||||
"modals.task.titlePlaceholder": {
|
||||
"source": "c8196f1d1039c2fb290add52ee990c571173d6f1",
|
||||
"translation": "dee0035d1027b937237c8bbdd6e77288df356ff4"
|
||||
|
|
@ -11572,6 +11612,22 @@
|
|||
"source": "77f4b7a081b20f78557dd404e14d91b89b52a27c",
|
||||
"translation": "b6a500e983b64d611aab3a9d5b2ec65fd4511f10"
|
||||
},
|
||||
"views.releaseNotes.title": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "eb15567c6afcd90288bcd72e1a8b2529f4f9c30f"
|
||||
},
|
||||
"views.releaseNotes.header": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "eb15567c6afcd90288bcd72e1a8b2529f4f9c30f"
|
||||
},
|
||||
"views.releaseNotes.viewAllLink": {
|
||||
"source": "b37e5d2fb2faa630817557713df6363f4bd0f5cc",
|
||||
"translation": "bb9554fdea3b306e3154c79005b21c6230c2cc5b"
|
||||
},
|
||||
"views.releaseNotes.starMessage": {
|
||||
"source": "de98980ccdae9c93e30d1172d4c15c059ea0508c",
|
||||
"translation": "25d41272c6bff10b1fba1a61f6db2e8f9df40425"
|
||||
},
|
||||
"settings.tabs.general": {
|
||||
"source": "9239ee2cda84eca4c3440e2a7b50148af67da3d4",
|
||||
"translation": "5376df989fac86247d5cd9f983d11ece28e75fcd"
|
||||
|
|
@ -14432,6 +14488,10 @@
|
|||
"source": "3f3714587b4802efeb6baf380a59615b8faf0c10",
|
||||
"translation": "e4c5963ce721f4bb182d474d1a9c0c604325c274"
|
||||
},
|
||||
"commands.viewReleaseNotes": {
|
||||
"source": "04c2072af97cf70c22fbf9efa9b62eb2574d23d6",
|
||||
"translation": "e8e1d32313d229666301e29a37df418032835142"
|
||||
},
|
||||
"modals.task.titlePlaceholder": {
|
||||
"source": "c8196f1d1039c2fb290add52ee990c571173d6f1",
|
||||
"translation": "4ad6efca173a22d4bf622d5729c3ad13612e6902"
|
||||
|
|
@ -17036,6 +17096,22 @@
|
|||
"source": "77f4b7a081b20f78557dd404e14d91b89b52a27c",
|
||||
"translation": "7deced4ee8b6e75d5dcafff58c7bd89905c98fd6"
|
||||
},
|
||||
"views.releaseNotes.title": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "b04d2e20a60a122b2f4926df86d88940f3050b39"
|
||||
},
|
||||
"views.releaseNotes.header": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "b04d2e20a60a122b2f4926df86d88940f3050b39"
|
||||
},
|
||||
"views.releaseNotes.viewAllLink": {
|
||||
"source": "b37e5d2fb2faa630817557713df6363f4bd0f5cc",
|
||||
"translation": "968c8961a28e089f98db843076f0e224b4770f94"
|
||||
},
|
||||
"views.releaseNotes.starMessage": {
|
||||
"source": "de98980ccdae9c93e30d1172d4c15c059ea0508c",
|
||||
"translation": "e3b958998079c079c491b83f4f167887d8ba3c01"
|
||||
},
|
||||
"settings.tabs.general": {
|
||||
"source": "9239ee2cda84eca4c3440e2a7b50148af67da3d4",
|
||||
"translation": "f0aaccbc0dcda37daa045cb4cda85177bedafdb0"
|
||||
|
|
@ -19890,6 +19966,10 @@
|
|||
"source": "3f3714587b4802efeb6baf380a59615b8faf0c10",
|
||||
"translation": "4f7b9505464a8b039fee24745afe2a1c951b81d3"
|
||||
},
|
||||
"commands.viewReleaseNotes": {
|
||||
"source": "04c2072af97cf70c22fbf9efa9b62eb2574d23d6",
|
||||
"translation": "2add1152032ee15c68c3fc05a7923fc50d2d0c31"
|
||||
},
|
||||
"modals.task.titlePlaceholder": {
|
||||
"source": "c8196f1d1039c2fb290add52ee990c571173d6f1",
|
||||
"translation": "0e65840f941f2c5e030cf553e4e5a3cc315fe73d"
|
||||
|
|
@ -22419,6 +22499,22 @@
|
|||
"source": "77f4b7a081b20f78557dd404e14d91b89b52a27c",
|
||||
"translation": "a82231aecd1ee2ec08d32031cf19b6f6a4f2842e"
|
||||
},
|
||||
"views.releaseNotes.title": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "92e2d6dcf90925e3073f30916467f8d01ead921a"
|
||||
},
|
||||
"views.releaseNotes.header": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "92e2d6dcf90925e3073f30916467f8d01ead921a"
|
||||
},
|
||||
"views.releaseNotes.viewAllLink": {
|
||||
"source": "b37e5d2fb2faa630817557713df6363f4bd0f5cc",
|
||||
"translation": "4caaa179ece78972b5be06967cd5e5c37ee1d241"
|
||||
},
|
||||
"views.releaseNotes.starMessage": {
|
||||
"source": "de98980ccdae9c93e30d1172d4c15c059ea0508c",
|
||||
"translation": "c2f8b36f59bc9f660cf0c1bd566fde7f11490dd6"
|
||||
},
|
||||
"settings.tabs.general": {
|
||||
"source": "9239ee2cda84eca4c3440e2a7b50148af67da3d4",
|
||||
"translation": "fdd17d17b54069e4f68253b0af0b1a50d389b199"
|
||||
|
|
@ -25246,6 +25342,10 @@
|
|||
"source": "3f3714587b4802efeb6baf380a59615b8faf0c10",
|
||||
"translation": "1ce699b6bccf33a45ff58320f4dfeb2593c3111e"
|
||||
},
|
||||
"commands.viewReleaseNotes": {
|
||||
"source": "04c2072af97cf70c22fbf9efa9b62eb2574d23d6",
|
||||
"translation": "060c1aa179717a8ebedce8eeae250cf12307291d"
|
||||
},
|
||||
"modals.task.titlePlaceholder": {
|
||||
"source": "c8196f1d1039c2fb290add52ee990c571173d6f1",
|
||||
"translation": "fb99b9f5be8916e4a7b038e3d1d9d9087f8a5653"
|
||||
|
|
@ -27850,6 +27950,22 @@
|
|||
"source": "77f4b7a081b20f78557dd404e14d91b89b52a27c",
|
||||
"translation": "227f72b88ebec3e37158e855352776b82662a27c"
|
||||
},
|
||||
"views.releaseNotes.title": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "f2780c1c443bdaf2d9eba3d81667be844efaf310"
|
||||
},
|
||||
"views.releaseNotes.header": {
|
||||
"source": "5939771f391859041bc57e5e05b04235b1ef8ee7",
|
||||
"translation": "f2780c1c443bdaf2d9eba3d81667be844efaf310"
|
||||
},
|
||||
"views.releaseNotes.viewAllLink": {
|
||||
"source": "b37e5d2fb2faa630817557713df6363f4bd0f5cc",
|
||||
"translation": "60abcbc397bbac657dcc27c7bb37870086d7dd18"
|
||||
},
|
||||
"views.releaseNotes.starMessage": {
|
||||
"source": "de98980ccdae9c93e30d1172d4c15c059ea0508c",
|
||||
"translation": "68e964844caa7bf91e74ffd31d2121483f126d1c"
|
||||
},
|
||||
"settings.tabs.general": {
|
||||
"source": "9239ee2cda84eca4c3440e2a7b50148af67da3d4",
|
||||
"translation": "f1484fa78b69777c083f5b19555ee4d232d70163"
|
||||
|
|
@ -30695,6 +30811,10 @@
|
|||
"source": "3f3714587b4802efeb6baf380a59615b8faf0c10",
|
||||
"translation": "f4fa2d18fff78b531c07f83bbc7753c26dbc05d9"
|
||||
},
|
||||
"commands.viewReleaseNotes": {
|
||||
"source": "04c2072af97cf70c22fbf9efa9b62eb2574d23d6",
|
||||
"translation": "524c479f706f46cb1f6e70be920671d9ed610e5c"
|
||||
},
|
||||
"modals.task.titlePlaceholder": {
|
||||
"source": "c8196f1d1039c2fb290add52ee990c571173d6f1",
|
||||
"translation": "37d9b0a0a59872345ce5e206027f8eccf793e6fa"
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ module.exports = {
|
|||
// Mock utility modules
|
||||
'^../../src/utils/helpers$': '<rootDir>/tests/__mocks__/utils.ts',
|
||||
'^../../src/utils/filenameGenerator$': '<rootDir>/tests/__mocks__/utils.ts',
|
||||
'^../../src/utils/dateUtils$': '<rootDir>/tests/__mocks__/utils.ts'
|
||||
'^../../src/utils/dateUtils$': '<rootDir>/tests/__mocks__/utils.ts',
|
||||
// Mock markdown files (for release notes)
|
||||
'\\.md$': '<rootDir>/tests/__mocks__/markdown.ts'
|
||||
},
|
||||
collectCoverageFrom: [
|
||||
'src/services/**/*.ts',
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
"description": "Note-based task management with calendar, pomodoro and time-tracking integration.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"build": "npm run build-css && tsc -noEmit --skipLibCheck && node esbuild.config.mjs production",
|
||||
"build": "npm run build-css && node generate-release-notes-import.mjs && tsc -noEmit --skipLibCheck && node esbuild.config.mjs production",
|
||||
"dev": "npm run build && npm run copy-files",
|
||||
"dev:watch": "npm run build-css && node esbuild.config.mjs",
|
||||
"dev:watch": "npm run build-css && node generate-release-notes-import.mjs && node esbuild.config.mjs",
|
||||
"copy-files": "node copy-files.mjs",
|
||||
"build-css": "node build-css.mjs",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json",
|
||||
"version": "node version-bump.mjs && node generate-release-notes-import.mjs && git add manifest.json versions.json src/releaseNotes.ts",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:coverage": "jest --coverage",
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ export const de: TranslationTree = {
|
|||
minTime: "Min. Zeit (Minuten)",
|
||||
},
|
||||
},
|
||||
releaseNotes: {
|
||||
title: "Was ist neu in TaskNotes {version}",
|
||||
header: "Was ist neu in TaskNotes {version}",
|
||||
viewAllLink: "Alle Versionshinweise auf GitHub anzeigen →",
|
||||
starMessage: "Wenn Sie TaskNotes nützlich finden, geben Sie ihm bitte einen Stern auf GitHub",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
tabs: {
|
||||
|
|
@ -1530,6 +1536,7 @@ export const de: TranslationTree = {
|
|||
pauseResumePomodoro: "Pomodoro-Timer pausieren/fortsetzen",
|
||||
refreshCache: "Cache aktualisieren",
|
||||
exportAllTasksIcs: "Alle Aufgaben als ICS-Datei exportieren",
|
||||
viewReleaseNotes: "Versionshinweise anzeigen",
|
||||
},
|
||||
modals: {
|
||||
task: {
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ export const en: TranslationTree = {
|
|||
minTime: "Min Time (minutes)",
|
||||
},
|
||||
},
|
||||
releaseNotes: {
|
||||
title: "What's new in TaskNotes {version}",
|
||||
header: "What's new in TaskNotes {version}",
|
||||
viewAllLink: "View all release notes on GitHub →",
|
||||
starMessage: "If you find TaskNotes useful, please consider giving it a star on GitHub",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
tabs: {
|
||||
|
|
@ -1496,6 +1502,7 @@ export const en: TranslationTree = {
|
|||
pauseResumePomodoro: "Pause/resume pomodoro timer",
|
||||
refreshCache: "Refresh cache",
|
||||
exportAllTasksIcs: "Export all tasks as ICS file",
|
||||
viewReleaseNotes: "View release notes",
|
||||
},
|
||||
modals: {
|
||||
task: {
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ export const es: TranslationTree = {
|
|||
minTime: "Tiempo mínimo (minutos)",
|
||||
},
|
||||
},
|
||||
releaseNotes: {
|
||||
title: "Novedades en TaskNotes {version}",
|
||||
header: "Novedades en TaskNotes {version}",
|
||||
viewAllLink: "Ver todas las notas de versión en GitHub →",
|
||||
starMessage: "Si TaskNotes te resulta útil, considera darle una estrella en GitHub",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
tabs: {
|
||||
|
|
@ -1540,6 +1546,7 @@ export const es: TranslationTree = {
|
|||
pauseResumePomodoro: "Pausar/reanudar temporizador pomodoro",
|
||||
refreshCache: "Actualizar caché",
|
||||
exportAllTasksIcs: "Exportar todas las tareas como archivo ICS",
|
||||
viewReleaseNotes: "Ver notas de versión",
|
||||
},
|
||||
modals: {
|
||||
task: {
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ export const fr: TranslationTree = {
|
|||
minTime: "Temps min (minutes)",
|
||||
},
|
||||
},
|
||||
releaseNotes: {
|
||||
title: "Nouveautés de TaskNotes {version}",
|
||||
header: "Nouveautés de TaskNotes {version}",
|
||||
viewAllLink: "Voir toutes les notes de version sur GitHub →",
|
||||
starMessage: "Si vous trouvez TaskNotes utile, pensez à lui donner une étoile sur GitHub",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
tabs: {
|
||||
|
|
@ -1541,6 +1547,7 @@ export const fr: TranslationTree = {
|
|||
pauseResumePomodoro: "Mettre en pause/reprendre le minuteur Pomodoro",
|
||||
refreshCache: "Actualiser le cache",
|
||||
exportAllTasksIcs: "Exporter toutes les tâches en fichier ICS",
|
||||
viewReleaseNotes: "Voir les notes de version",
|
||||
},
|
||||
modals: {
|
||||
task: {
|
||||
|
|
|
|||
|
|
@ -205,6 +205,12 @@ export const ja: TranslationTree = {
|
|||
minTime: "最小時間(分)",
|
||||
},
|
||||
},
|
||||
releaseNotes: {
|
||||
title: "TaskNotes {version} の新機能",
|
||||
header: "TaskNotes {version} の新機能",
|
||||
viewAllLink: "GitHubですべてのリリースノートを表示 →",
|
||||
starMessage: "TaskNotesが役に立ったら、GitHubでスターをお願いします",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
tabs: {
|
||||
|
|
@ -1487,6 +1493,7 @@ export const ja: TranslationTree = {
|
|||
pauseResumePomodoro: "ポモドーロタイマーを一時停止/再開",
|
||||
refreshCache: "キャッシュを更新",
|
||||
exportAllTasksIcs: "すべてのタスクをICSファイルとしてエクスポート",
|
||||
viewReleaseNotes: "リリースノートを表示",
|
||||
},
|
||||
modals: {
|
||||
task: {
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ export const ru: TranslationTree = {
|
|||
minTime: "Мин. время (минуты)",
|
||||
},
|
||||
},
|
||||
releaseNotes: {
|
||||
title: "Что нового в TaskNotes {version}",
|
||||
header: "Что нового в TaskNotes {version}",
|
||||
viewAllLink: "Посмотреть все примечания к выпуску на GitHub →",
|
||||
starMessage: "Если TaskNotes полезен для вас, поставьте звезду на GitHub",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
tabs: {
|
||||
|
|
@ -1507,6 +1513,7 @@ export const ru: TranslationTree = {
|
|||
pauseResumePomodoro: "Приостановить/возобновить таймер помодоро",
|
||||
refreshCache: "Обновить кэш",
|
||||
exportAllTasksIcs: "Экспортировать все задачи как файл ICS",
|
||||
viewReleaseNotes: "Посмотреть примечания к выпуску",
|
||||
},
|
||||
modals: {
|
||||
task: {
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ export const zh: TranslationTree = {
|
|||
minTime: "最少时间(分钟)",
|
||||
},
|
||||
},
|
||||
releaseNotes: {
|
||||
title: "TaskNotes {version} 的新功能",
|
||||
header: "TaskNotes {version} 的新功能",
|
||||
viewAllLink: "在 GitHub 上查看所有版本说明 →",
|
||||
starMessage: "如果您觉得 TaskNotes 有用,请在 GitHub 上给它加星",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
tabs: {
|
||||
|
|
@ -1432,6 +1438,7 @@ export const zh: TranslationTree = {
|
|||
pauseResumePomodoro: "暂停/恢复番茄钟计时器",
|
||||
refreshCache: "刷新缓存",
|
||||
exportAllTasksIcs: "导出所有任务为ICS文件",
|
||||
viewReleaseNotes: "查看版本说明",
|
||||
},
|
||||
modals: {
|
||||
task: {
|
||||
|
|
|
|||
51
src/main.ts
51
src/main.ts
|
|
@ -94,6 +94,8 @@ import { AutoExportService } from "./services/AutoExportService";
|
|||
// Type-only import for HTTPAPIService (actual import is dynamic on desktop only)
|
||||
import type { HTTPAPIService } from "./services/HTTPAPIService";
|
||||
import { createI18nService, I18nService, TranslationKey } from "./i18n";
|
||||
import { ReleaseNotesView, RELEASE_NOTES_VIEW_TYPE } from "./views/ReleaseNotesView";
|
||||
import { CURRENT_RELEASE_NOTES } from "./releaseNotes";
|
||||
|
||||
interface TranslatedCommandDefinition {
|
||||
id: string;
|
||||
|
|
@ -461,6 +463,11 @@ export default class TaskNotesPlugin extends Plugin {
|
|||
|
||||
this.registerView(KANBAN_VIEW_TYPE, (leaf) => new KanbanView(leaf, this));
|
||||
|
||||
this.registerView(
|
||||
RELEASE_NOTES_VIEW_TYPE,
|
||||
(leaf) => new ReleaseNotesView(leaf, this, CURRENT_RELEASE_NOTES, this.manifest.version)
|
||||
);
|
||||
|
||||
// Register essential editor extensions (now safe after layout ready)
|
||||
this.registerEditorExtension(createTaskLinkOverlay(this));
|
||||
|
||||
|
|
@ -639,6 +646,9 @@ export default class TaskNotesPlugin extends Plugin {
|
|||
|
||||
// Migration check was moved to early startup - just show prompts here if needed
|
||||
await this.showMigrationPromptsIfNeeded();
|
||||
|
||||
// Check for version updates and show release notes if needed
|
||||
await this.checkForVersionUpdate();
|
||||
} catch (error) {
|
||||
console.error("Error during lazy service initialization:", error);
|
||||
}
|
||||
|
|
@ -886,6 +896,36 @@ export default class TaskNotesPlugin extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for version updates and show release notes if needed
|
||||
*/
|
||||
private async checkForVersionUpdate(): Promise<void> {
|
||||
try {
|
||||
const currentVersion = this.manifest.version;
|
||||
const lastSeenVersion = this.settings.lastSeenVersion;
|
||||
|
||||
// If this is a new install or version has changed, show release notes
|
||||
if (lastSeenVersion && lastSeenVersion !== currentVersion) {
|
||||
// Show release notes after a delay to ensure UI is ready
|
||||
setTimeout(async () => {
|
||||
await this.activateReleaseNotesView();
|
||||
// Update lastSeenVersion immediately after showing the release notes
|
||||
// This ensures they only show once per version
|
||||
this.settings.lastSeenVersion = currentVersion;
|
||||
await this.saveSettings();
|
||||
}, 1500); // Slightly longer delay than migration to avoid conflicts
|
||||
}
|
||||
|
||||
// Update lastSeenVersion if it hasn't been set yet (new install)
|
||||
if (!lastSeenVersion) {
|
||||
this.settings.lastSeenVersion = currentVersion;
|
||||
await this.saveSettings();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error checking for version update:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method for views to wait for migration completion
|
||||
*/
|
||||
|
|
@ -1429,6 +1469,13 @@ export default class TaskNotesPlugin extends Plugin {
|
|||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "view-release-notes",
|
||||
nameKey: "commands.viewReleaseNotes",
|
||||
callback: async () => {
|
||||
await this.activateReleaseNotesView();
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
this.registerCommands();
|
||||
|
|
@ -1560,6 +1607,10 @@ export default class TaskNotesPlugin extends Plugin {
|
|||
return this.activateView(KANBAN_VIEW_TYPE);
|
||||
}
|
||||
|
||||
async activateReleaseNotesView() {
|
||||
return this.activateView(RELEASE_NOTES_VIEW_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open and activate the search pane with a tag query
|
||||
* (Renamed from openSearchPaneWithTag for cleaner API)
|
||||
|
|
|
|||
5
src/markdown.d.ts
vendored
Normal file
5
src/markdown.d.ts
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// Type declarations for importing markdown files as strings
|
||||
declare module "*.md" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
|
|
@ -238,6 +238,8 @@ export const DEFAULT_SETTINGS: TaskNotesSettings = {
|
|||
customPriorities: DEFAULT_PRIORITIES,
|
||||
// Migration defaults
|
||||
recurrenceMigrated: false,
|
||||
// Release notes defaults
|
||||
lastSeenVersion: undefined,
|
||||
// Status bar defaults
|
||||
showTrackedTasksInStatusBar: false,
|
||||
// Time tracking defaults
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// import { TAbstractFile } from 'obsidian';
|
||||
import { Setting } from "obsidian";
|
||||
import TaskNotesPlugin from "../../main";
|
||||
import {
|
||||
createSectionHeader,
|
||||
|
|
@ -226,4 +227,20 @@ export function renderGeneralTab(
|
|||
save();
|
||||
},
|
||||
});
|
||||
|
||||
// Release Notes Section
|
||||
createSectionHeader(container, "Release Notes");
|
||||
createHelpText(container, `Current version: ${plugin.manifest.version}`);
|
||||
|
||||
new Setting(container)
|
||||
.setName("View release notes")
|
||||
.setDesc("See what's new in the latest version of TaskNotes")
|
||||
.addButton((button) =>
|
||||
button
|
||||
.setButtonText("View release notes")
|
||||
.setCta()
|
||||
.onClick(async () => {
|
||||
await plugin.activateReleaseNotesView();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ export interface TaskNotesSettings {
|
|||
customPriorities: PriorityConfig[];
|
||||
// Migration tracking
|
||||
recurrenceMigrated?: boolean;
|
||||
// Release notes tracking
|
||||
lastSeenVersion?: string;
|
||||
// Status bar settings
|
||||
showTrackedTasksInStatusBar: boolean;
|
||||
// Time tracking settings
|
||||
|
|
|
|||
102
src/views/ReleaseNotesView.ts
Normal file
102
src/views/ReleaseNotesView.ts
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import { ItemView, WorkspaceLeaf, MarkdownRenderer } from "obsidian";
|
||||
import TaskNotesPlugin from "../main";
|
||||
|
||||
export const RELEASE_NOTES_VIEW_TYPE = "tasknotes-release-notes";
|
||||
|
||||
const GITHUB_RELEASES_URL = "https://github.com/callumalpass/tasknotes/releases";
|
||||
|
||||
export class ReleaseNotesView extends ItemView {
|
||||
plugin: TaskNotesPlugin;
|
||||
private releaseNotes: string;
|
||||
private version: string;
|
||||
|
||||
constructor(leaf: WorkspaceLeaf, plugin: TaskNotesPlugin, releaseNotes: string, version: string) {
|
||||
super(leaf);
|
||||
this.plugin = plugin;
|
||||
this.releaseNotes = releaseNotes;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
getViewType(): string {
|
||||
return RELEASE_NOTES_VIEW_TYPE;
|
||||
}
|
||||
|
||||
getDisplayText(): string {
|
||||
return this.plugin.i18n.translate("views.releaseNotes.title", { version: this.version });
|
||||
}
|
||||
|
||||
getIcon(): string {
|
||||
return "book-open";
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform issue references like (#123) into clickable GitHub issue links
|
||||
*/
|
||||
private transformIssueLinks(markdown: string): string {
|
||||
const repoUrl = "https://github.com/callumalpass/tasknotes";
|
||||
return markdown.replace(/\(#(\d+)\)/g, `([#$1](${repoUrl}/issues/$1))`);
|
||||
}
|
||||
|
||||
async onOpen() {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
contentEl.addClass("tasknotes-release-notes-view");
|
||||
|
||||
// Create a container for the markdown content
|
||||
const container = contentEl.createDiv({ cls: "tasknotes-release-notes-container" });
|
||||
container.style.padding = "20px";
|
||||
container.style.maxWidth = "900px";
|
||||
container.style.margin = "0 auto";
|
||||
|
||||
// Header with version
|
||||
const header = container.createEl("div", { cls: "release-notes-header" });
|
||||
header.style.marginBottom = "20px";
|
||||
header.createEl("h1", {
|
||||
text: this.plugin.i18n.translate("views.releaseNotes.header", { version: this.version })
|
||||
});
|
||||
|
||||
// Markdown content
|
||||
const markdownContainer = container.createEl("div", { cls: "release-notes-content" });
|
||||
markdownContainer.style.marginBottom = "30px";
|
||||
|
||||
// Transform issue references into clickable links and render the markdown
|
||||
const transformedNotes = this.transformIssueLinks(this.releaseNotes);
|
||||
await MarkdownRenderer.render(
|
||||
this.plugin.app,
|
||||
transformedNotes,
|
||||
markdownContainer,
|
||||
"",
|
||||
this as any
|
||||
);
|
||||
|
||||
// Footer with link to all releases
|
||||
const footer = container.createEl("div", { cls: "release-notes-footer" });
|
||||
footer.style.borderTop = "1px solid var(--background-modifier-border)";
|
||||
footer.style.paddingTop = "20px";
|
||||
footer.style.textAlign = "center";
|
||||
|
||||
const link = footer.createEl("a", {
|
||||
text: this.plugin.i18n.translate("views.releaseNotes.viewAllLink"),
|
||||
href: GITHUB_RELEASES_URL,
|
||||
});
|
||||
link.style.color = "var(--text-accent)";
|
||||
link.style.textDecoration = "none";
|
||||
link.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
window.open(GITHUB_RELEASES_URL, "_blank");
|
||||
});
|
||||
|
||||
// Star message
|
||||
const starMessage = footer.createEl("p", {
|
||||
text: this.plugin.i18n.translate("views.releaseNotes.starMessage"),
|
||||
});
|
||||
starMessage.style.marginTop = "16px";
|
||||
starMessage.style.fontSize = "0.9em";
|
||||
starMessage.style.color = "var(--text-muted)";
|
||||
}
|
||||
|
||||
async onClose() {
|
||||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
}
|
||||
}
|
||||
3
tests/__mocks__/markdown.ts
Normal file
3
tests/__mocks__/markdown.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// Mock for markdown file imports
|
||||
// Used to prevent Jest from trying to parse .md files as JavaScript
|
||||
export default "# Mock Release Notes\n\nThis is a mock markdown file for testing purposes.";
|
||||
|
|
@ -25,6 +25,7 @@ describe('Settings UI - User Fields (optional)', () => {
|
|||
(plugin as any).settings = { ...DEFAULT_SETTINGS };
|
||||
(plugin as any).i18n = createI18nService();
|
||||
(plugin as any).registerEvent = jest.fn();
|
||||
(plugin as any).manifest = { version: '0.0.0' };
|
||||
|
||||
const tab = new TaskNotesSettingTab(app, plugin);
|
||||
tab.display();
|
||||
|
|
|
|||
Loading…
Reference in a new issue