diff --git a/manifest.json b/manifest.json index d867baa..a46c983 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "gamified-pkm", "name": "Gamificate your PKM", - "version": "0.0.88", + "version": "0.0.89", "minAppVersion": "0.15.0", "description": "Enhance your Personal Knowledge Management with gamification elements. Boost motivation and achieve growth as you engage with your PKM.", "author": "Andreas Trebing", diff --git a/package-lock.json b/package-lock.json index b94be99..a8bf6c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "obsidian-gamified-pkm", - "version": "0.0.88", + "version": "0.0.89", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "obsidian-gamified-pkm", - "version": "0.0.88", + "version": "0.0.89", "license": "MIT", "dependencies": { "crypto-js": "^4.1.1", diff --git a/package.json b/package.json index dcdf9e8..06d0091 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-gamified-pkm", - "version": "0.0.88", + "version": "0.0.89", "description": "Enhance your Personal Knowledge Management with gamification elements. Boost motivation and achieve growth as you engage with your PKM.", "main": "main.js", "scripts": { diff --git a/src/constants.ts b/src/constants.ts index 60dfd78..46eedff 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,11 +1,12 @@ import { Badge } from './badges' -export const pointsNoteMajurity: number = 100; -export const pointsMajurity: number = 10; -export const pointsForDailyChallenge: number = 500; -export const pointsForWeeklyChallenge: number = 2000; -export const streakboosterDecrease: number = 0.2; -export const streakboosterIncreaseDaily: number = 0.1; -export const streakboosterIncreaseWeekly: number = 1; +export const pointsNoteMajurity = 100; +export const pointsMajurity = 10; +export const pointsForDailyChallenge = 500; +export const pointsForWeeklyChallenge = 2000; +export const streakboosterDecrease = 0.2; +export const streakboosterIncreaseDaily = 0.1; +export const streakboosterIncreaseWeekly = 1; +// eslint-disable-next-line @typescript-eslint/no-var-requires export const CryptoJS = require("crypto-js"); export const secretKey = "2ZU^12y#QmNB5$yEin5^"; export const debugLogs = false; diff --git a/src/main.ts b/src/main.ts index c97e709..ac5a7d2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -53,9 +53,12 @@ export default class gamification extends Plugin { private statusBarItem = this.addStatusBarItem(); private statusbarGamification = this.statusBarItem.createEl("span", { text: "" }); public settings: ISettings; + private lastEditTimes: Record = {}; + private editTimers: Record> = {}; - getSettingString(key: string) { + + getSettingString(key: string): string { const decryptedValue = this.settings[key] !== undefined ? this.settings[key].toString() : '' //if(debugLogs) console.debug(`String: decrypted ${key} is ${decryptString(decryptedValue)}`) return decryptString(decryptedValue); @@ -126,7 +129,7 @@ export default class gamification extends Plugin { // take care to reset when opened on a new day, don't wait for trigger setTimeout(async () => { - // Code that you want to execute after the delay + // Code to execute after the delay await this.loadSettings(); await this.resetDailyGoals() await this.updateStatusBar(this.statusbarGamification) @@ -137,8 +140,13 @@ export default class gamification extends Plugin { this.timerInterval = 30 * 60 * 1000; // minutes x seconds x milliseconds this.timerId = window.setInterval(this.resetDailyGoals.bind(this), this.timerInterval); - + this.registerEvent( + this.app.workspace.on('editor-change', this.onEditorChanged.bind(this)) + ); + this.registerEvent( + this.app.vault.on('rename', this.onFileRenamed.bind(this)) + ); if (this.getSettingBoolean('debug')){ this.addRibbonIcon("accessibility", "Crafting", async () => { @@ -290,6 +298,73 @@ export default class gamification extends Plugin { } + async onEditorChanged() { + const activeView = this.app.workspace.getActiveViewOfType(MarkdownView); + if (!activeView) return; + + const activeFile = activeView.file; + if (!activeFile) return; + + //this.getSettingString('folderExclude') + const foldersToExclude = this.getSettingString('folderExclude'); + const folderNames = foldersToExclude.split(',').map(folder => folder.trim()); + + const isInExcludedFolder = folderNames.some(folderName => activeFile.path.includes(folderName)); + + if (isInExcludedFolder) return; + + const currentTime = Date.now(); + + const fileLastModifiedTime = activeFile.stat.mtime || 0; + + // Check if the file was recently modified by comparing the last modification time + if (currentTime - fileLastModifiedTime < 900) { + return; + } + + // Update last edit time for the file + this.lastEditTimes[activeFile.path] = currentTime; + + // Clear previous timer if exists + if (this.editTimers[activeFile.path]) { + clearTimeout(this.editTimers[activeFile.path]); + } + + this.editTimers[activeFile.path] = setTimeout(() => { + // Check if no further edits happened within the delay + if (this.lastEditTimes[activeFile.path] === currentTime) { + // Trigger your action here + this.triggerAction(activeFile.path); + } + }, this.getSettingNumber('autoRateOnChangeDelayTime') * 1000); + } + + + + onFileRenamed(oldPath: string, newPath: string) { + console.log(`${newPath}`); + const foldersToExclude = this.getSettingString('folderExclude'); + console.log(`foldersToExclude: ${foldersToExclude}`); + const folderNames = foldersToExclude.split(',').map(folder => folder.trim() + '/'); + + const isInExcludedFolder = folderNames.some(folderName => newPath.includes(folderName)); + + if (isInExcludedFolder) { + console.log(isInExcludedFolder); + return; + } + + this.triggerAction(newPath); + } + + + triggerAction(filePath: string) { + if(this.getSettingBoolean('autoRateOnChange')){ + this.calculateNoteMajurity().then(r => console.log(r)); + //if(debugLogs) console.log(`File ${filePath} was edited and no further changes occurred.`); + } + } + private async resetGame() { await this.removeKeysFromFrontmatter(); this.setSettingNumber('statusLevel', 1) @@ -459,6 +534,10 @@ export default class gamification extends Plugin { clearInterval(this.timerId); this.timerId = null; } + + for (const timerId in this.editTimers) { + clearTimeout(this.editTimers[timerId]); + } } diff --git a/src/maturitycalculation.ts b/src/maturitycalculation.ts index 05e8278..1e42ed1 100644 --- a/src/maturitycalculation.ts +++ b/src/maturitycalculation.ts @@ -1,5 +1,6 @@ import { TFile, App, } from 'obsidian'; import * as path from 'path'; +import {debugLogs} from "./constants"; export function rateProgressiveSummarization(charCountTotal: number, layer2count: number, layer3count: number): number { const percentLayer2 = layer2count * 100 / charCountTotal; @@ -407,7 +408,7 @@ export function count_inlinks(file: TFile): number { const { app: { metadataCache: { resolvedLinks } } } = this; const { path } = file; - console.log('Resolved Links Data:', resolvedLinks); // Add this line + if(debugLogs) console.log('Resolved Links Data:', resolvedLinks); // Add this line const sumInlinks = Object.values(resolvedLinks) .map((val: { [key: string]: number }) => val[path] ?? 0) diff --git a/src/settings.ts b/src/settings.ts index 46ff1fa..754e194 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -92,7 +92,9 @@ export const defaultSettings: Partial = { delayLoadTime: "U2FsdGVkX19TLndonGY4Y8vHuZFfLJ5gZ2t/CLprh0o=", timeShowNotice: "U2FsdGVkX190u8cOsylOs1cQ8MeZFq+i+Wv4ox6qq0k=", receivedBadges: "U2FsdGVkX1/skTUHmzuMYD86hDA/uF1kElPVYm04ijQ=", - showNewVersionNotification: "U2FsdGVkX1+7lWe/h95uqzgl27JBGW2iki7sBwk44YQ=" + showNewVersionNotification: "U2FsdGVkX1+7lWe/h95uqzgl27JBGW2iki7sBwk44YQ=", + autoRateOnChange: "U2FsdGVkX1/KT5I5txOiZ+r6Aa1F5RuE5b4eqpaZAqQ=", + autoRateOnChangeDelayTime: "U2FsdGVkX1/RiGtHePLD9og+g+w+DL31vVK02vCSkQQ=" }; export interface DynamicSettings { @@ -184,6 +186,8 @@ export interface ISettings extends DynamicSettings{ timeShowNotice: string; receivedBadges: string; showNewVersionNotification: string + autoRateOnChange: string + autoRateOnChangeDelayTime: string //[key: string]: number | string | boolean | MomentInput; } @@ -275,6 +279,8 @@ export class GamificationPluginSettings extends PluginSettingTab { public timeShowNotice: string; public receivedBadges: string; public showNewVersionNotification: string; + public autoRateOnChange: string; + public autoRateOnChangeDelayTime: string; constructor(app: App, plugin: gamification) { super(app, plugin); @@ -374,6 +380,29 @@ export class GamificationPluginSettings extends PluginSettingTab { }), ); + new Setting(containerEl) + .setName('enable auto rate after change') + .setDesc('you can enable here an automatic trigger to rate a note when changed/created') + .addToggle((toggle) => + toggle + .setValue(decryptBoolean(this.plugin.settings.autoRateOnChange)) + .onChange((value) => { + this.plugin.settings.autoRateOnChange = encryptBoolean(value); + this.plugin.saveData(this.plugin.settings); + }), + ); + new Setting(containerEl) + .setName('Wait time for automatic note rating') + .setDesc('Enter in seconds how long to wait after a change before automatical note ratting will be done') + .addText(text => text + .setPlaceholder('5') + .setValue(decryptNumber(this.plugin.settings.autoRateOnChangeDelayTime).toString()) + //.setValue("0") + .onChange(async (value) => { + this.plugin.settings.autoRateOnChangeDelayTime = encryptNumber(parseInt(value)); + await this.plugin.saveSettings(); + })); + new Setting(containerEl) .setName('Delay load settings at startup')