diff --git a/esbuild.config.mjs b/esbuild.config.mjs
index f431974..c1323eb 100644
--- a/esbuild.config.mjs
+++ b/esbuild.config.mjs
@@ -53,6 +53,9 @@ const jsContext = await esbuild.context({
treeShaking: true,
outfile: "dist/main.js",
minify: prod,
+ loader: {
+ ".md": "text",
+ },
plugins: [copyPlugin],
});
diff --git a/src/BanyanAppData.ts b/src/BanyanAppData.ts
index 7e7ab23..0a68ace 100644
--- a/src/BanyanAppData.ts
+++ b/src/BanyanAppData.ts
@@ -4,10 +4,7 @@ import { DefaultRandomReviewFilter, RandomReviewFilter } from "./models/RandomRe
import { SortType } from "./models/Enum";
import { getToday } from "./utils/utils";
-export const CUR_APP_DATA_VERSION = 1;
-
export interface BanyanAppData {
- version: number;
// in app
sortType: SortType;
firstUseDate: string;
@@ -24,7 +21,6 @@ export interface BanyanAppData {
export const DEFAULT_APP_DATA: BanyanAppData = {
- version: CUR_APP_DATA_VERSION,
// in app
sortType: 'created',
firstUseDate: getToday(),
diff --git a/src/BanyanPlugin.ts b/src/BanyanPlugin.ts
index 154f96b..52559f8 100644
--- a/src/BanyanPlugin.ts
+++ b/src/BanyanPlugin.ts
@@ -1,11 +1,13 @@
import { Plugin, WorkspaceLeaf } from 'obsidian';
import { BanyanPluginSettings, DEFAULT_SETTINGS, CUR_SETTINGS_VERSION } from './BanyanPluginSettings';
-import { BanyanAppData, DEFAULT_APP_DATA, CUR_APP_DATA_VERSION } from './BanyanAppData';
+import { BanyanAppData, DEFAULT_APP_DATA } from './BanyanAppData';
import { CARD_DASHBOARD_VIEW_TYPE, CardDashboard } from './pages/CardDashboard';
import { BanyanSettingTab } from './BanyanSettingTab';
import { FileUtils } from './utils/fileUtils';
import { i18n } from './utils/i18n';
import { TagFilter, isEmptyTagFilter } from './models/TagFilter';
+import { AnnouncementModal } from './components/AnnouncementModal';
+import { getWelcomeMarkdown, getChangelogMarkdown } from './utils/announcements';
export default class BanyanPlugin extends Plugin {
@@ -82,6 +84,44 @@ export default class BanyanPlugin extends Plugin {
});
}
+ checkAnnouncements = async () => {
+ const curVersion = this.manifest.version;
+ const lastVersion = this.settings.lastVersion;
+ const settingVersion = this.settings.settingsVersion;
+
+ if ((!lastVersion || lastVersion === '') && settingVersion === CUR_SETTINGS_VERSION) {
+ // 初次启动
+ const modal = new AnnouncementModal(this.app, {
+ type: 'welcome',
+ content: getWelcomeMarkdown(),
+ onClose: () => {
+ this.settings.lastVersion = curVersion;
+ this.saveSettings();
+ }
+ });
+ modal.open();
+ } else if (lastVersion !== curVersion) {
+ // 版本更新
+ const updateContent = getChangelogMarkdown();
+ if (updateContent && updateContent.trim().length > 0) {
+ const modal = new AnnouncementModal(this.app, {
+ type: 'update',
+ content: updateContent,
+ onClose: () => {
+ this.settings.lastVersion = curVersion;
+ this.saveSettings();
+ }
+ });
+ modal.open();
+ } else {
+ // 如果当前版本没有更新公告,也更新版本号,避免重复检查
+ this.settings.lastVersion = curVersion;
+ await this.saveSettings();
+ }
+ }
+ }
+
+
onunload() {
// do nothing
}
@@ -120,7 +160,7 @@ export default class BanyanPlugin extends Plugin {
setupRandomReview = () => {
if (!this.settings.enableRandomReview) return;
-
+
const icons = ['dice', 'shuffle', 'dices', 'dice-6',
'dice-5', 'dice-4', 'dice-3', 'dice-2', 'dice-1'];
this.randomRibbonIcons = [];
@@ -143,7 +183,7 @@ export default class BanyanPlugin extends Plugin {
});
}
- updateSettingIfNeeded = async () => {
+ updateSettingIfNeeded = () => {
// *** 版本更新时,在以下添加更新逻辑 ***
if (this.settings.settingsVersion < 2) {
const getNewFilterIfNeeded = (tf: TagFilter) => {
@@ -199,7 +239,7 @@ export default class BanyanPlugin extends Plugin {
}
if (this.settings.settingsVersion < 9) {
const usedViewSchemes = this.appData.viewSchemes && this.appData.viewSchemes.length > 0;
-
+
let usedRandomReview = false;
if (this.appData.randomReviewFilters && this.appData.randomReviewFilters.length > 0) {
if (this.appData.randomReviewFilters.length > 1) {
@@ -212,8 +252,8 @@ export default class BanyanPlugin extends Plugin {
this.settings.enableViewSchemes = usedViewSchemes;
this.settings.enableRandomReview = usedRandomReview;
}
+ this.checkAnnouncements();
this.settings.settingsVersion = CUR_SETTINGS_VERSION;
- this.appData.version = CUR_APP_DATA_VERSION;
this.updateSavedFile();
this.saveSettings();
this.saveAppData();
@@ -276,7 +316,6 @@ export default class BanyanPlugin extends Plugin {
if (migrated) {
console.log('Detected legacy settings, migrated to appData');
- this.appData.version = CUR_APP_DATA_VERSION;
await this.saveAppData();
await this.saveSettings();
}
diff --git a/src/BanyanPluginSettings.ts b/src/BanyanPluginSettings.ts
index d0673d6..44602e0 100644
--- a/src/BanyanPluginSettings.ts
+++ b/src/BanyanPluginSettings.ts
@@ -24,6 +24,8 @@ export interface BanyanPluginSettings {
enableViewSchemes?: boolean;
enableRandomReview?: boolean;
+ // meta
+ lastVersion?: string;
}
export const CUR_SETTINGS_VERSION = 9;
@@ -52,4 +54,5 @@ export const DEFAULT_SETTINGS: BanyanPluginSettings = {
enableViewSchemes: false,
enableRandomReview: false,
+ lastVersion: '',
}
\ No newline at end of file
diff --git a/src/BanyanSettingTab.tsx b/src/BanyanSettingTab.tsx
index 7bc6396..4c9659d 100644
--- a/src/BanyanSettingTab.tsx
+++ b/src/BanyanSettingTab.tsx
@@ -6,6 +6,8 @@ import { useCombineStore } from './store';
import { CardContentMaxHeightType, FontTheme, NewNoteLocationMode } from './models/Enum';
import { openMigrateTitleModal } from './components/MigrateTitleModal';
import { openRemoveIdModal } from './components/RemoveIdModal';
+import { AnnouncementModal } from './components/AnnouncementModal';
+import { getWelcomeMarkdown, getChangelogMarkdown } from './utils/announcements';
export class BanyanSettingTab extends PluginSettingTab {
plugin: BanyanPlugin;
@@ -23,8 +25,6 @@ export class BanyanSettingTab extends PluginSettingTab {
this.setupCardsDirectorySetting(containerEl);
this.setupOpenWhenStartObsidianSetting(containerEl);
this.setupCardsColumnsSetting(containerEl);
- this.setupEnableViewSchemesSetting(containerEl);
- this.setupEnableRandomReviewSetting(containerEl);
// 卡片视图
new Setting(containerEl).setName(i18n.t('setting_header_cards')).setHeading();
@@ -40,11 +40,18 @@ export class BanyanSettingTab extends PluginSettingTab {
this.setupUseZkPrefixerFormatSetting(containerEl);
this.setupShowAddNoteRibbonSetting(containerEl);
+ // 帮助
+ new Setting(containerEl).setName(i18n.t('setting_header_help')).setHeading();
+ this.setupHelpSetting(containerEl);
+
// 旧版清理
new Setting(containerEl).setName(i18n.t('setting_header_clean')).setHeading();
+ this.setupEnableViewSchemesSetting(containerEl);
+ this.setupEnableRandomReviewSetting(containerEl);
this.setupMigrateTitleToFilenameSetting(containerEl);
}
+
setupCardsDirectorySetting(containerEl: HTMLElement) {
const dateDesc = document.createDocumentFragment();
dateDesc.appendText(i18n.t('setting_note_directory_desc1'));
@@ -288,4 +295,33 @@ export class BanyanSettingTab extends PluginSettingTab {
});
}
+ setupHelpSetting(containerEl: HTMLElement) {
+ new Setting(containerEl)
+ .setName(i18n.t('setting_show_welcome_name'))
+ .setDesc(i18n.t('setting_show_welcome_desc'))
+ .addButton(btn => {
+ btn.setButtonText(i18n.t('setting_show_welcome_btn'))
+ .onClick(async () => {
+ const modal = new AnnouncementModal(this.app, {
+ type: 'welcome',
+ content: getWelcomeMarkdown()
+ });
+ modal.open();
+ });
+ });
+ new Setting(containerEl)
+ .setName(i18n.t('setting_show_update_name'))
+ .setDesc(i18n.t('setting_show_update_desc'))
+ .addButton(btn => {
+ btn.setButtonText(i18n.t('setting_show_update_btn'))
+ .onClick(async () => {
+ const modal = new AnnouncementModal(this.app, {
+ type: 'update',
+ content: getChangelogMarkdown()
+ });
+ modal.open();
+ });
+ });
+ }
+
}
diff --git a/docs/changelog.md b/src/announcements/changelog_en.md
similarity index 90%
rename from docs/changelog.md
rename to src/announcements/changelog_en.md
index 291c26c..35e7683 100644
--- a/docs/changelog.md
+++ b/src/announcements/changelog_en.md
@@ -1,4 +1,14 @@
-### Changelog
+# Changelog
+
+### 1.4.3
+
+Improvements
+
+- Now we have guidance pop-up and changelog pop-up, which can also be viewed in the settings panel.
+- Now we add switches for "Random Review" and "View Scheme" in the setting. If you have been using these features, all remains the same; otherwise, they are disabled by default. These two features may be considered for removal in later version.
+- We optimized the refresh logic of the card panel. Now Adding or editing notes will no longer cause a full refresh of the card panel.
+- Fixed the extra blank block appeared in the search box on mobile.
+- Optimized some styles.
### 1.4.2
diff --git a/docs/changelog_zh.md b/src/announcements/changelog_zh.md
similarity index 89%
rename from docs/changelog_zh.md
rename to src/announcements/changelog_zh.md
index 526e90b..668c1aa 100644
--- a/docs/changelog_zh.md
+++ b/src/announcements/changelog_zh.md
@@ -1,4 +1,17 @@
-### 更新日志
+# 更新日志
+
+### 1.4.3
+
+新增
+
+- 指引弹窗和版本更新日志弹窗,并且可以在设置面板中主动查看。
+- 「随机回顾」和「视图空间」的设置开关,如果你使用过该功能,开关是打开的,使用照旧;否则默认是关闭的,日后考虑下掉这2个功能。
+
+修复和优化
+
+- 优化了卡片面板的刷新逻辑,现在新增或修改笔记不会再导致卡片面板全量刷新了。
+- 修复移动端搜索框出现额外空白块的问题。
+- 对一些样式进行了优化。
### 1.4.2
diff --git a/src/announcements/welcome_en.md b/src/announcements/welcome_en.md
new file mode 100644
index 0000000..5aed79f
--- /dev/null
+++ b/src/announcements/welcome_en.md
@@ -0,0 +1,25 @@
+# 🌲 Welcome to Banyan
+
+Banyan allows you to visualize your notes through a card view and retrieve them using a tag-based filtering system, rather than a traditional tree directory.
+
+### 🚀 Getting Started
+
+This plugin only manages notes within the `Notes Directory` (defaulted to `cards`).
+The storage structure of notes and subdirectories within this folder is no longer important.
+The `banyan_config` under the "Notes Directory" stores plugin configuration files. It cannot be hidden for now, as setting it to a hidden directory will cause the MD files within it to fail to load.
+
+The Card Panel displays notes chronologically and allows you to view specific notes through filtering schemes.
+Filters include tags, dates, and keywords. Tags can be combined using **"OR, AND, NOT"** logic to create powerful filtering combinations.
+Click the **Card Icon** 🗂️ in the functional area to open the Card Panel.
+
+Click the **Lightbulb Icon** 💡 in the functional area to create a new note.
+The current time is used as the default title, but you can modify it as you wish.
+New notes are stored by default in a `Year/Quarter/Month/Day` hierarchy—though the hierarchy is secondary, you can customize the storage directory in the settings.
+
+*Please feel free to explore more. Happy learning in your forest of knowledge!*
+
+### 📮 Contact Me
+
+github issue: [obsidian-banyan - ratiger | Github](https://github.com/ratiger/obsidian-banyan)
+email: 2084939306@qq.com
+rednote: ratiger (rednote number: 1392996322)
diff --git a/src/announcements/welcome_zh.md b/src/announcements/welcome_zh.md
new file mode 100644
index 0000000..4a7c609
--- /dev/null
+++ b/src/announcements/welcome_zh.md
@@ -0,0 +1,26 @@
+# 🌲 欢迎使用 Banyan
+
+Banyan 通过卡片视图直观查看笔记内容,并通过以标签为主的筛选方案,而非传统的树形目录来检索笔记。
+
+### 🚀 基本使用
+
+本插件只管理「笔记目录」(默认为 `cards`)下的笔记;
+该目录下的笔记与子目录的存放结构不再紧要。
+「笔记目录」的根目录下的「banyan_config」目录用于存储应用配置文件,暂时无法隐藏,因为设置为隐藏目录会导致其内的md文件读取失败。
+
+卡片面板以时间顺序展示笔记,并通过筛选方案展示指定笔记;
+筛选包括标签、日期、关键字,其中标签通过「或且非」组合出强大的筛选方案;
+点击功能区的卡片图标 🗂️ 打开卡片面板。
+
+点击功能区的灯泡图标 💡 新建笔记;
+默认以当时时间作为新建笔记的标题,但你可以任意修改它;
+新建笔记将默认按 `年/季度/月/日` 的层级存放,但层级其实无关紧要,不过你也可以在设置中自定义存放目录;
+
+*尽请探索更多内容,祝您在的知识森林中学习愉快!*
+
+### 📮 与我联系
+
+github issue: [obsidian-banyan - ratiger | Github](https://github.com/ratiger/obsidian-banyan)
+邮箱: 2084939306@qq.com
+小红书: ratiger (小红书号: 1392996322)
+
diff --git a/src/components/AnnouncementModal.tsx b/src/components/AnnouncementModal.tsx
new file mode 100644
index 0000000..7fcb2c7
--- /dev/null
+++ b/src/components/AnnouncementModal.tsx
@@ -0,0 +1,63 @@
+import { App, Modal, MarkdownRenderer, Component } from "obsidian";
+import * as React from "react";
+import { createRoot, Root } from "react-dom/client";
+import { i18n } from "src/utils/i18n";
+
+interface AnnouncementModalProps {
+ type: 'welcome' | 'update';
+ content: string;
+ onClose?: () => void;
+}
+
+export class AnnouncementModal extends Modal {
+ props: AnnouncementModalProps;
+ root: Root | null = null;
+
+ constructor(app: App, props: AnnouncementModalProps) {
+ super(app);
+ this.props = props;
+ }
+
+ onOpen() {
+ this.modalEl.addClass('announcement-modal');
+ this.root = createRoot(this.modalEl);
+ this.root.render(
+
+ { this.close() }} />
+
+ );
+ (this as any).shouldRestoreSelection = false;
+ }
+
+ onClose() {
+ this.root?.unmount();
+ this.props.onClose?.();
+ }
+}
+
+const AnnouncementContainer = ({ app, props, close }: {
+ app: App, props: AnnouncementModalProps, close: () => void
+}) => {
+ const { type, content } = props;
+ const buttonText = type === 'welcome' ? i18n.t('announcement_get_started') : i18n.t('announcement_close');
+ const contentRef = React.useRef(null);
+
+ React.useEffect(() => {
+ if (contentRef.current) {
+ contentRef.current.empty();
+ const component = new Component();
+ component.load();
+ MarkdownRenderer.render(app, content, contentRef.current, '', component);
+ }
+ }, [content, app]);
+
+ return (
+
+ );
+};
diff --git a/src/components/components.css b/src/components/components.css
index 0916ffe..b4821d3 100644
--- a/src/components/components.css
+++ b/src/components/components.css
@@ -246,4 +246,52 @@
font-size: 32px;
cursor: pointer;
transition: box-shadow 0.2s, background 0.2s;
+}
+
+/* 公告弹窗 */
+.announcement-modal {
+ max-width: 500px;
+}
+
+.announcement-container {
+ padding: 24px;
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+}
+
+.announcement-content {
+ line-height: 1.6;
+ max-height: 65vh;
+ overflow-y: auto;
+ padding-right: 12px;
+ scrollbar-width: none; /* Firefox */
+ -ms-overflow-style: none; /* IE and Edge */
+}
+
+.announcement-content::-webkit-scrollbar {
+ display: none; /* Chrome, Safari and Opera */
+}
+
+.announcement-content h1:first-child {
+ margin-top: 0;
+ text-align: center;
+ color: var(--text-accent);
+}
+
+.announcement-content h3 {
+ margin-top: 1.5em;
+ border-bottom: 1px solid var(--background-modifier-border);
+ padding-bottom: 0.3em;
+}
+
+.announcement-footer {
+ display: flex;
+ justify-content: center;
+}
+
+.announcement-btn {
+ width: 100%;
+ padding: 10px !important;
+ font-weight: bold !important;
}
\ No newline at end of file
diff --git a/src/declarations.d.ts b/src/declarations.d.ts
new file mode 100644
index 0000000..dc003b7
--- /dev/null
+++ b/src/declarations.d.ts
@@ -0,0 +1,4 @@
+declare module "*.md" {
+ const content: string;
+ export default content;
+}
diff --git a/src/utils/announcements.ts b/src/utils/announcements.ts
new file mode 100644
index 0000000..dbc0e2d
--- /dev/null
+++ b/src/utils/announcements.ts
@@ -0,0 +1,19 @@
+import { i18n } from "./i18n";
+
+// Import markdown files as strings
+import welcome_en from "../announcements/welcome_en.md";
+import welcome_zh from "../announcements/welcome_zh.md";
+import changelog_en from "../announcements/changelog_en.md";
+import changelog_zh from "../announcements/changelog_zh.md";
+
+export const getWelcomeMarkdown = (): string => {
+ const lang = i18n.getCurrentLanguage();
+ if (lang === 'zh') return welcome_zh;
+ return welcome_en;
+};
+
+export const getChangelogMarkdown = (): string => {
+ const lang = i18n.getCurrentLanguage();
+ if (lang === 'zh') return changelog_zh;
+ return changelog_en;
+};
diff --git a/src/utils/i18n/languages/en.ts b/src/utils/i18n/languages/en.ts
index 2e89d32..3f90489 100644
--- a/src/utils/i18n/languages/en.ts
+++ b/src/utils/i18n/languages/en.ts
@@ -108,10 +108,10 @@ export default {
setting_card_content_max_height_expand: "Expand",
setting_enable_view_schemes_name: "Enable \"View schemes\"",
- setting_enable_view_schemes_desc: "Whether to display and enable the \"View schemes\" feature in the sidebar.",
-
+ setting_enable_view_schemes_desc: "Most of the use cases of this feature are replaced by \"Filter schemes\". So we are considering removing it.",
+
setting_enable_random_review_name: "Enable \"Random review\"",
- setting_enable_random_review_desc: "Whether to display and enable the \"Random review\" feature in the sidebar.",
+ setting_enable_random_review_desc: "Most of the use cases of this feature are replaced by \"Random browse\". So we are considering removing it.",
// font
setting_font_theme_name: "Font size",
@@ -234,4 +234,18 @@ export default {
loading_text: "Loading...",
reached_bottom: "You have reached the bottom.~",
+ /* Announcement Modal */
+ announcement_welcome_title: "Welcome to Banyan",
+ announcement_update_title: "What's New in Banyan",
+ announcement_get_started: "Get Started",
+ announcement_close: "Close",
+
+ /* Settings - Help */
+ setting_header_help: "❓ Help",
+ setting_show_welcome_name: "Tutorial",
+ setting_show_welcome_desc: "About Banyan usage.",
+ setting_show_welcome_btn: "View",
+ setting_show_update_name: "Changelog",
+ setting_show_update_desc: "All versions changelog.",
+ setting_show_update_btn: "View",
};
\ No newline at end of file
diff --git a/src/utils/i18n/languages/zh.ts b/src/utils/i18n/languages/zh.ts
index ecb437d..5fbeab5 100644
--- a/src/utils/i18n/languages/zh.ts
+++ b/src/utils/i18n/languages/zh.ts
@@ -62,7 +62,7 @@ export default {
setting_header_basic: "⚙️ 基础设置",
setting_header_cards: "🗂 卡片视图",
setting_header_editor: "✏️ 新建笔记",
- setting_header_clean: "⚠️ 旧版数据清理",
+ setting_header_clean: "⚠️ 旧版清理",
setting_note_directory_name: "笔记目录",
setting_note_directory_desc1: "「卡片面板」只会管理该目录下的所有笔记。",
@@ -109,11 +109,11 @@ export default {
setting_card_content_max_height_normal: "一般",
setting_card_content_max_height_expand: "不折叠",
- setting_enable_view_schemes_name: "启用「视图空间」",
- setting_enable_view_schemes_desc: "是否在侧边栏显示并在后台启用「视图空间」功能。",
-
- setting_enable_random_review_name: "启用「随机回顾」",
- setting_enable_random_review_desc: "是否在侧边栏显示并在后台启用「随机回顾」功能。",
+ setting_enable_view_schemes_name: "启用「视图空间」功能",
+ setting_enable_view_schemes_desc: "该功能的使用场景更多被「筛选方案」替代了,故正考虑下掉该功能。",
+
+ setting_enable_random_review_name: "启用「随机回顾」功能",
+ setting_enable_random_review_desc: "该功能的使用场景更多被「乱序浏览」替代了,故正考虑下掉该功能。",
// 字体
setting_font_theme_name: "内容区域字体大小",
@@ -236,4 +236,18 @@ export default {
loading_text: "加载中...",
reached_bottom: "你已经到底部了",
+ /* Announcement Modal */
+ announcement_welcome_title: "欢迎使用 Banyan",
+ announcement_update_title: "Banyan 更新日志",
+ announcement_get_started: "开始使用",
+ announcement_close: "关闭",
+
+ /* 设置 - 帮助 */
+ setting_header_help: "❓ 帮助",
+ setting_show_welcome_name: "新手指引",
+ setting_show_welcome_desc: "关于 Banyan 的使用说明。",
+ setting_show_welcome_btn: "查看",
+ setting_show_update_name: "更新日志",
+ setting_show_update_desc: "所有版本的更新内容。",
+ setting_show_update_btn: "查看",
};
\ No newline at end of file