Skip to content

Commit

Permalink
feat: mobile support added
Browse files Browse the repository at this point in the history
  • Loading branch information
mahmudz committed Aug 25, 2024
1 parent 41b1f2d commit b682fbb
Show file tree
Hide file tree
Showing 13 changed files with 485 additions and 217 deletions.
4 changes: 2 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"id": "favorite-note",
"name": "Favorite Note",
"version": "1.0.5",
"version": "2.0.0",
"minAppVersion": "0.15.0",
"description": "Mark your note as favorite.",
"author": "mahmudz",
"authorUrl": "https://github.com/mahmudz",
"fundingUrl": "https://www.buymeacoffee.com/mahmudz",
"isDesktopOnly": false
}
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "obsidian-sample-plugin",
"version": "1.0.5",
"version": "2.0.0",
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
"main": "main.js",
"scripts": {
Expand All @@ -21,4 +21,4 @@
"tslib": "2.4.0",
"typescript": "4.7.4"
}
}
}
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FavoritePluginSettings } from "./types";

export const DEFAULT_SETTINGS: FavoritePluginSettings = {
icon: "star",
favorites: [],
favorites: new Set<string>(),
};

export const SETTINGS_ICON_BTN_ID = "fv-select-icon-btn";
215 changes: 14 additions & 201 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,215 +1,28 @@
import { Plugin, TFile } from "obsidian";
import { DEFAULT_SETTINGS } from "src/constants";
import { FavoritePluginSettings } from "src/types";
import { createFavoriteButton } from "./lib/utils";
import FavoritePluginSettingsTab from "./tabs/settings-tab";
import "../styles.css";
import { App, Platform, Plugin, PluginManifest } from "obsidian";
import { BasePlugin } from "./variants/BasePlugin";
import { DesktopPlugin } from "./variants/DesktopPlugin";
import { MobilePlugin } from "./variants/MobilePlugin";

export default class FavoritePlugin extends Plugin {
private isEnabled = false;
variant: BasePlugin;

settings: FavoritePluginSettings;
private favorites: string[] = [];
constructor(app: App, manifest: PluginManifest) {
super(app, manifest);

getFileExplorer(): HTMLElement | null {
return this.app.workspace.containerEl.find(".nav-files-container");
}

onFolderExpand(e: PointerEvent) {
if (this.isEnabled) {
this.addFavoriteIconToFolder(e.currentTarget as HTMLDivElement);
} else {
const parentElement = e.currentTarget as HTMLElement;

this.removeFavoriteIconFromChild(parentElement);
if (Platform.isDesktop) {
this.variant = new DesktopPlugin(this, this.app);
}
}

isFavorite(filePath: string): boolean {
return this.favorites.includes(filePath);
}

toggleFavorite(filePath: string) {
const index = this.favorites.indexOf(filePath);

if (index !== -1) {
this.favorites.splice(index, 1);
} else {
this.favorites.push(filePath);
}

this.saveSettings();
}

addFavoriteIconToItem(listItem: HTMLElement | Element) {
const filePath = listItem.getAttribute("data-path") ?? "";

const trailingButton = createFavoriteButton(
this.isFavorite(filePath),
this.settings.icon
);

trailingButton.addEventListener("click", (e: PointerEvent) => {
const favoriteButton = e.currentTarget as HTMLDivElement;
if (favoriteButton) {
const titleEl = favoriteButton.parentElement as HTMLDivElement;
const filePath = titleEl.getAttribute("data-path") as string;

this.toggleFavorite(filePath);

if (this.isFavorite(filePath)) {
favoriteButton.classList.add("is-favorite");
} else {
favoriteButton.classList.remove("is-favorite");
}
}
});

listItem.appendChild(trailingButton);
}

addFavoriteIconToFolder(folderEl: HTMLElement) {
const listItems = folderEl.querySelectorAll(
".nav-folder, .nav-file-title"
);

listItems.forEach((listItem) => {
const isAlreadyExists = listItem.find(".fav-btn");

if (isAlreadyExists) {
return;
}

if (listItem.classList.contains("nav-file-title")) {
listItem.addClass("fav-nav-file-title");

this.addFavoriteIconToItem(listItem);
} else if (!listItem.classList.contains("is-collapsed")) {
// Becuase of empty note list on inital call
setTimeout(() => {
this.addFavoriteIconToFolder(listItem as HTMLDivElement);
}, 200);
} else {
listItem.addEventListener(
"click",
this.onFolderExpand.bind(this),
{ once: true }
);
}
});
}

addFavoriteIcons() {
const parent = this.getFileExplorer();

if (parent) {
this.addFavoriteIconToFolder(parent);
if (Platform.isMobile) {
this.variant = new MobilePlugin(this, this.app);
}
}

removeFavoriteIconFromChild(folderEl: HTMLElement) {
const listItems = folderEl.querySelectorAll(
".nav-folder, .nav-file-title"
);

listItems.forEach((listItem) => {
if (listItem.classList.contains("nav-file-title")) {
listItem.findAll(".fav-btn").forEach((el) => el.remove());
listItem.removeClass("fav-nav-file-title");
} else {
this.removeFavoriteIconFromChild(listItem as HTMLDivElement);
}
});
}

removeFavoriteIcons() {
const fileExplorer = this.getFileExplorer();

if (fileExplorer) {
this.removeFavoriteIconFromChild(fileExplorer);
}
}

async loadSettings() {
this.settings = Object.assign(
{},
DEFAULT_SETTINGS,
await this.loadData()
);

this.favorites = this.settings.favorites;
}

async saveSettings() {
await this.saveData({
...this.settings,
favorites: this.favorites,
});
}

reload() {
this.removeFavoriteIcons();

this.addFavoriteIcons();
}

onFileCreate(file: TFile) {
setTimeout(() => {
const listItem = this.app.workspace.containerEl.find(
`[data-path="${file.path}"]`
);

listItem.classList.add("fav-nav-file-title");

this.addFavoriteIconToItem(listItem);
}, 100);
}

onFileDelete(file: TFile) {
const index = this.favorites.indexOf(file.path);

if (index !== -1) {
this.favorites.splice(index, 1);

this.saveSettings();
}
}

async onload() {
this.isEnabled = true;

this.app.workspace.onLayoutReady(async () => {
await this.loadSettings();

this.addFavoriteIcons();

this.getFileExplorer()
?.findAll(".nav-file-title")
.forEach((el) => {
el.classList.add("fav-nav-file-title");
});

this.app.vault.on("create", this.onFileCreate.bind(this));

this.app.vault.on("delete", this.onFileDelete.bind(this));
});

this.addSettingTab(new FavoritePluginSettingsTab(this.app, this));
onload() {
this.variant?.onload();
}

onunload() {
this.isEnabled = false;

this.getFileExplorer()
?.findAll(".nav-file-title")
.forEach((el) => {
el.classList.remove("fav-nav-file-title");
});

this.app.vault.off("create", this.onFileCreate.bind(this));

this.app.vault.off("delete", this.onFileDelete.bind(this));

this.removeFavoriteIcons();
this.variant?.destroy();
}
}
6 changes: 3 additions & 3 deletions src/modals/choose-icon-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class ChooseFromIconList extends FuzzySuggestModal<string> {
}

async onChooseItem(item: string): Promise<void> {
this.plugin.settings.icon = item;
this.plugin.variant.settings.icon = item;

setIcon(
document.querySelector(
Expand All @@ -56,9 +56,9 @@ export class ChooseFromIconList extends FuzzySuggestModal<string> {
item
);

await this.plugin.saveSettings();
await this.plugin.variant.saveSettings();

this.plugin.reload();
this.plugin.variant.reload();

setTimeout(() => {
dispatchEvent(new Event("print-greeting-to-console"));
Expand Down
4 changes: 2 additions & 2 deletions src/tabs/settings-tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ export default class FavoritePluginSettingsTab extends PluginSettingTab {
.setName("Favorite Icon")
.setDesc("Choose your favorite icon")
.addButton((el) => {
el.setIcon(this.plugin.settings.icon);
el.setIcon(this.plugin.variant.settings.icon);

el.onClick(async () => {
new ChooseFromIconList(this.plugin, false).open();
});

this.plugin.saveSettings();
this.plugin.variant.saveSettings();
})
.controlEl.children[0].setAttr("id", SETTINGS_ICON_BTN_ID);

Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export interface FavoritePluginSettings {
icon: string;
favorites: string[];
favorites: Set<string>;
}
69 changes: 69 additions & 0 deletions src/variants/BasePlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { App, Plugin, TFile } from "obsidian";
import { DEFAULT_SETTINGS } from "src/constants";
import { FavoritePluginSettings } from "src/types";

abstract class BasePluginContract {
abstract onload(): void;
abstract destroy(): void;
abstract reload(): void;
}

export abstract class BasePlugin extends BasePluginContract {
plugin: Plugin;
app: App;
isEnabled = false;
settings: FavoritePluginSettings;
favorites: Set<string>;

constructor(plugin: Plugin, app: App) {
super();

this.plugin = plugin;
this.app = app;
this.init();
}

async init() {
await this.loadSettings();
}

async loadSettings() {
this.settings = Object.assign(
{},
DEFAULT_SETTINGS,
await this.plugin.loadData()
);
this.favorites = new Set(Object.values(this.settings.favorites));
}

async saveSettings() {
await this.plugin.saveData({
...this.settings,
favorites: Object.assign({}, Array.from(this.favorites)),
});
}

isFavorite(filePath: string): boolean {
return this.favorites.has(filePath);
}

removeFavorite(filePath: string) {
this.favorites.delete(filePath);

this.saveSettings();
}

onFileDelete(file: TFile) {
this.removeFavorite(file.path);
}

toggleFavorite(filePath: string) {
if (this.isFavorite(filePath)) {
this.favorites.delete(filePath);
} else {
this.favorites.add(filePath);
}

this.saveSettings();
}
}
Loading

0 comments on commit b682fbb

Please sign in to comment.