├── .github
├── FUNDING.yml
└── workflows
│ └── release.yml
├── .gitignore
├── LICENSE
├── README.md
├── manifest.json
├── package.json
├── rollup.config.js
├── src
├── main.ts
├── types.ts
├── ui
│ ├── commandSuggester.ts
│ ├── iconPicker.ts
│ ├── icons.ts
│ ├── macroModal.ts
│ └── settingsTab.ts
└── util.ts
├── styles.css
├── tsconfig.json
└── versions.json
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: ['phibr0']
2 | custom: ['https://www.buymeacoffee.com/phibr0']
3 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release Obsidian Plugin
2 | on:
3 | push:
4 | # Sequence of patterns matched against refs/tags
5 | tags:
6 | - '*' # Push events to matching any tag format, i.e. 1.0, 20.15.10
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | with:
13 | fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
14 | - name: Use Node.js
15 | uses: actions/setup-node@v1
16 | with:
17 | node-version: '14.x' # You might need to adjust this value to your own version
18 | # Get the version number and put it in a variable
19 | - name: Get Version
20 | id: version
21 | run: |
22 | echo "::set-output name=tag::$(git describe --abbrev=0)"
23 | # Build the plugin
24 | - name: Build
25 | id: build
26 | run: |
27 | npm install
28 | npm run build --if-present
29 | # Package the required files into a zip
30 | - name: Package
31 | run: |
32 | mkdir ${{ github.event.repository.name }}
33 | cp main.js manifest.json styles.css README.md ${{ github.event.repository.name }}
34 | zip -r ${{ github.event.repository.name }}.zip ${{ github.event.repository.name }}
35 | # Create the release on github
36 | - name: Create Release
37 | id: create_release
38 | uses: actions/create-release@v1
39 | env:
40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41 | VERSION: ${{ github.ref }}
42 | with:
43 | tag_name: ${{ github.ref }}
44 | release_name: ${{ github.ref }}
45 | draft: false
46 | prerelease: false
47 | # Upload the packaged release file
48 | - name: Upload zip file
49 | id: upload-zip
50 | uses: actions/upload-release-asset@v1
51 | env:
52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53 | with:
54 | upload_url: ${{ steps.create_release.outputs.upload_url }}
55 | asset_path: ./${{ github.event.repository.name }}.zip
56 | asset_name: ${{ github.event.repository.name }}.zip
57 | asset_content_type: application/zip
58 | # Upload the main.js
59 | - name: Upload main.js
60 | id: upload-main
61 | uses: actions/upload-release-asset@v1
62 | env:
63 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
64 | with:
65 | upload_url: ${{ steps.create_release.outputs.upload_url }}
66 | asset_path: ./main.js
67 | asset_name: main.js
68 | asset_content_type: text/javascript
69 | # Upload the manifest.json
70 | - name: Upload manifest.json
71 | id: upload-manifest
72 | uses: actions/upload-release-asset@v1
73 | env:
74 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
75 | with:
76 | upload_url: ${{ steps.create_release.outputs.upload_url }}
77 | asset_path: ./manifest.json
78 | asset_name: manifest.json
79 | asset_content_type: application/json
80 | # Upload the style.css
81 | - name: Upload styles.css
82 | id: upload-css
83 | uses: actions/upload-release-asset@v1
84 | env:
85 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
86 | with:
87 | upload_url: ${{ steps.create_release.outputs.upload_url }}
88 | asset_path: ./styles.css
89 | asset_name: styles.css
90 | asset_content_type: text/css
91 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Intellij
2 | *.iml
3 | .idea
4 |
5 | # npm
6 | node_modules
7 | package-lock.json
8 |
9 | # build
10 | main.js
11 | *.js.map
12 |
13 | # obsidian
14 | data.json
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Phillip
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # This Plugin is now archived. [Commander](https://github.com/phibr0/obsidian-commander) is a work-in-progress successor!
2 |
3 | # Obsidian Macros [](https://github.com/phibr0/obsidian-macros/releases) 
4 |
5 | This plugin allows you to group as many commands as you wish together into one command (Macro). You can also specify an icon and set a delay between the commands.
6 |
7 | ## How to install
8 |
9 | 1. Go to **Community Plugins** in your [Obsidian](https://www.obsidian.md) settings and **disable** Safe Mode
10 | 2. Click on **Browse** and search for „Macros“
11 | 3. Click install
12 | 4. Toggle the plugin **on** in the **Community Plugins** tab
13 |
14 | ## Support me
15 |
16 | If you find this plugin helpful, consider supporting me:
17 |
18 |
19 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "macro-plugin",
3 | "name": "Macros",
4 | "version": "0.1.0",
5 | "minAppVersion": "0.12.11",
6 | "description": "Group multiple Commands into one Macro.",
7 | "author": "phibr0",
8 | "authorUrl": "https://github.com/phibr0/",
9 | "isDesktopOnly": false
10 | }
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "obsidian-sample-plugin",
3 | "version": "0.12.0",
4 | "description": "This is a sample plugin for Obsidian (https://obsidian.md)",
5 | "main": "main.js",
6 | "scripts": {
7 | "dev": "esbuild src/main.ts --bundle --external:obsidian --format=cjs --outfile=main.js --watch",
8 | "build": "rollup --config rollup.config.js --environment BUILD:production"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "MIT",
13 | "devDependencies": {
14 | "@rollup/plugin-commonjs": "^18.0.0",
15 | "@rollup/plugin-node-resolve": "^11.2.1",
16 | "@rollup/plugin-typescript": "^8.2.1",
17 | "@types/feather-icons": "^4.7.0",
18 | "@types/node": "^14.14.37",
19 | "obsidian": "^0.12.0",
20 | "rollup": "^2.32.1",
21 | "tslib": "^2.2.0",
22 | "typescript": "^4.2.4",
23 | "esbuild": "^0.12.19"
24 | },
25 | "dependencies": {
26 | "feather-icons": "^4.28.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import typescript from '@rollup/plugin-typescript';
2 | import {nodeResolve} from '@rollup/plugin-node-resolve';
3 | import commonjs from '@rollup/plugin-commonjs';
4 |
5 | const isProd = (process.env.BUILD === 'production');
6 |
7 | const banner =
8 | `/*
9 | THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
10 | if you want to view the source visit the plugins github repository
11 | */
12 | `;
13 |
14 | export default {
15 | input: 'src/main.ts',
16 | output: {
17 | dir: '.',
18 | sourcemap: 'inline',
19 | sourcemapExcludeSources: isProd,
20 | format: 'cjs',
21 | exports: 'default',
22 | banner,
23 | },
24 | external: ['obsidian'],
25 | plugins: [
26 | typescript(),
27 | nodeResolve({browser: true}),
28 | commonjs(),
29 | ]
30 | };
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { IconPicker } from './ui/iconPicker';
2 | import { App, ButtonComponent, Command, Modal, Notice, Platform, Plugin, PluginSettingTab, Setting } from 'obsidian';
3 | import { addFeatherIcons } from './ui/icons';
4 | import CommandSuggester from './ui/commandSuggester';
5 | import MacroSettingsTab from './ui/settingsTab';
6 | import { MacroSettings, DEFAULT_SETTINGS } from './types';
7 | import { wait } from './util';
8 |
9 |
10 | export default class MacroPlugin extends Plugin {
11 | settings: MacroSettings;
12 | iconList: string[] = ["any-key", "audio-file", "blocks", "bold-glyph", "bracket-glyph", "broken-link", "bullet-list", "bullet-list-glyph", "calendar-with-checkmark", "check-in-circle", "check-small", "checkbox-glyph", "checkmark", "clock", "cloud", "code-glyph", "create-new", "cross", "cross-in-box", "crossed-star", "csv", "deleteColumn", "deleteRow", "dice", "document", "documents", "dot-network", "double-down-arrow-glyph", "double-up-arrow-glyph", "down-arrow-with-tail", "down-chevron-glyph", "enter", "exit-fullscreen", "expand-vertically", "filled-pin", "folder", "formula", "forward-arrow", "fullscreen", "gear", "go-to-file", "hashtag", "heading-glyph", "help", "highlight-glyph", "horizontal-split", "image-file", "image-glyph", "indent-glyph", "info", "insertColumn", "insertRow", "install", "italic-glyph", "keyboard-glyph", "languages", "left-arrow", "left-arrow-with-tail", "left-chevron-glyph", "lines-of-text", "link", "link-glyph", "logo-crystal", "magnifying-glass", "microphone", "microphone-filled", "minus-with-circle", "moveColumnLeft", "moveColumnRight", "moveRowDown", "moveRowUp", "note-glyph", "number-list-glyph", "open-vault", "pane-layout", "paper-plane", "paused", "pdf-file", "pencil", "percent-sign-glyph", "pin", "plus-with-circle", "popup-open", "presentation", "price-tag-glyph", "quote-glyph", "redo-glyph", "reset", "right-arrow", "right-arrow-with-tail", "right-chevron-glyph", "right-triangle", "run-command", "search", "sheets-in-box", "sortAsc", "sortDesc", "spreadsheet", "stacked-levels", "star", "star-list", "strikethrough-glyph", "switch", "sync", "sync-small", "tag-glyph", "three-horizontal-bars", "trash", "undo-glyph", "unindent-glyph", "up-and-down-arrows", "up-arrow-with-tail", "up-chevron-glyph", "uppercase-lowercase-a", "vault", "vertical-split", "vertical-three-dots", "wrench-screwdriver-glyph"];
13 |
14 | async onload() {
15 | console.log('loading plugin');
16 |
17 | await this.loadSettings();
18 |
19 | addFeatherIcons(this.iconList);
20 |
21 | this.settings.macros.forEach(macro => {
22 | const command: Command = {
23 | id: macro.commandID,
24 | name: macro.name,
25 | callback: async () => {
26 | for (let i = 0; i < macro.commands.length; i++) {
27 | //@ts-ignore
28 | this.app.commands.executeCommandById(macro.commands[i]);
29 | await wait(macro.delay);
30 | }
31 | },
32 | icon: macro.icon,
33 | }
34 | this.addCommand(command);
35 | });
36 |
37 | this.addSettingTab(new MacroSettingsTab(this));
38 | }
39 |
40 | onunload() {
41 | console.log('unloading plugin');
42 | }
43 |
44 | async loadSettings() {
45 | this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
46 | }
47 |
48 | async saveSettings() {
49 | await this.saveData(this.settings);
50 | }
51 | }
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { Command } from "obsidian";
2 |
3 | export interface Macro {
4 | commandID: string;
5 | name: string;
6 | mobileOnly: boolean;
7 | icon: string;
8 | delay: number;
9 | commands: string[];
10 | command?: Command;
11 | }
12 |
13 | export interface MacroSettings {
14 | macros: Macro[];
15 | }
16 |
17 | export const DEFAULT_SETTINGS: MacroSettings = {
18 | macros: [],
19 | }
--------------------------------------------------------------------------------
/src/ui/commandSuggester.ts:
--------------------------------------------------------------------------------
1 | import { FuzzySuggestModal, Command } from "obsidian";
2 | import CustomSidebarPlugin from "src/main";
3 |
4 | export default class CommandSuggester extends FuzzySuggestModal {
5 |
6 | constructor(private plugin: CustomSidebarPlugin) {
7 | super(plugin.app);
8 | }
9 |
10 | getItems(): Command[] {
11 | //@ts-ignore
12 | return this.app.commands.listCommands();
13 | }
14 |
15 | getItemText(item: Command): string {
16 | return item.name;
17 | }
18 |
19 | async onChooseItem(item: Command, evt: MouseEvent | KeyboardEvent): Promise {
20 | this.close();
21 | setTimeout(() => {
22 | dispatchEvent(new CustomEvent("M-commandAdded", {detail: {command: item.id}}));
23 | }, 100);
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/src/ui/iconPicker.ts:
--------------------------------------------------------------------------------
1 | import { Command, FuzzyMatch, FuzzySuggestModal, setIcon } from "obsidian";
2 | import MacroPlugin from "src/main";
3 |
4 | export class IconPicker extends FuzzySuggestModal{
5 | plugin: MacroPlugin;
6 |
7 | constructor(plugin: MacroPlugin) {
8 | super(plugin.app);
9 | this.plugin = plugin;
10 | this.setPlaceholder("Pick an Icon");
11 | }
12 |
13 | private cap(string: string): string {
14 | const words = string.split(" ");
15 |
16 | return words.map((word) => {
17 | return word[0].toUpperCase() + word.substring(1);
18 | }).join(" ");
19 | }
20 |
21 | getItems(): string[] {
22 | return this.plugin.iconList;
23 | }
24 |
25 | getItemText(item: string): string {
26 | return this.cap(item.replace("feather-", "").replace(/-/ig, " "));
27 | }
28 |
29 | renderSuggestion(item: FuzzyMatch, el: HTMLElement): void {
30 | el.addClass("M-icon-container");
31 | const div = createDiv({ cls: "M-icon" });
32 | el.appendChild(div);
33 | setIcon(div, item.item);
34 | super.renderSuggestion(item, el);
35 | }
36 |
37 | async onChooseItem(item: string): Promise {
38 | this.close();
39 | setTimeout(() => {
40 | dispatchEvent(new CustomEvent("M-iconPicked", {detail: {icon: item}}));
41 | }, 100);
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/ui/icons.ts:
--------------------------------------------------------------------------------
1 | import * as feather from "feather-icons";
2 | import { addIcon } from "obsidian";
3 |
4 | export function addFeatherIcons(iconList: string[]) {
5 | Object.values(feather.icons).forEach((i) => {
6 | const svg = i.toSvg({viewBox: "0 0 24 24", width: "100", height: "100"});
7 | //Remove the svg tag: svg.match(/(?<=>).*(?=<\/svg>)/).first()
8 | addIcon("feather-" + i.name, svg);
9 | iconList.push("feather-" + i.name);
10 | });
11 | }
--------------------------------------------------------------------------------
/src/ui/macroModal.ts:
--------------------------------------------------------------------------------
1 | import { Modal, Command, Setting, Platform } from "obsidian";
2 | import MacroPlugin from "src/main";
3 | import { Macro } from "src/types";
4 | import { wait } from "src/util";
5 | import CommandSuggester from "./commandSuggester";
6 | import { IconPicker } from "./iconPicker";
7 |
8 | export default class MacroCreatorModal extends Modal {
9 | plugin: MacroPlugin;
10 | command: any;
11 | delay: number; //in ms
12 | name: string;
13 | coms: string[] = [];
14 | mobileOnly: boolean;
15 | editing: boolean;
16 |
17 | constructor(plugin: MacroPlugin, macro?: Macro) {
18 | super(plugin.app);
19 | this.plugin = plugin;
20 | this.command = macro?.command ?? {};
21 | this.delay = macro?.delay ?? 10;
22 | this.name = macro?.name;
23 | this.coms = macro?.commands ?? [];
24 | this.mobileOnly = macro?.mobileOnly ?? false;
25 | if (macro) {
26 | this.editing = true;
27 | } else {
28 | this.editing = false;
29 | }
30 | addEventListener("M-iconPicked", (e: CustomEvent) => {
31 | this.command.icon = e.detail.icon;
32 | this.display();
33 | });
34 | addEventListener("M-commandAdded", (e: CustomEvent) => {
35 | this.coms.push(e.detail.command);
36 | this.display();
37 | });
38 | }
39 |
40 | onOpen() {
41 | super.onOpen();
42 | this.display();
43 | }
44 |
45 | display() {
46 | const { contentEl: el } = this;
47 | const command = this.command as Command;
48 | el.empty();
49 | this.titleEl.setText("Add a new Macro")
50 |
51 | new Setting(el)
52 | .setName("Name")
53 | .setDesc("Specify the Name of your brand new Macro.")
54 | .addText(cb => {
55 | cb.setValue(command?.name?.replace(/Macro Plugin: /g, "") ?? "")
56 | .setPlaceholder("Super duper Macro")
57 | .setValue(this.name)
58 | .setDisabled(this.editing)
59 | .onChange(value => {
60 | this.name = value.trim().replace(/Macro Plugin: /g, "");
61 | command.name = value.trim().replace(/Macro Plugin: /g, "");
62 | command.id = value.trim().replace(/Macro Plugin: /g, "").replace(" ", "-").toLowerCase();
63 | });
64 | });
65 |
66 | new Setting(el)
67 | .setName("Icon")
68 | .setDesc("Pick an Icon for your Macro.")
69 | .addButton(bt => {
70 | bt.setDisabled(this.editing);
71 | if (command.icon) {
72 | bt.setIcon(command.icon);
73 | } else {
74 | bt.setButtonText("Pick Icon");
75 | }
76 | bt.onClick(() => {
77 | new IconPicker(this.plugin).open();
78 | });
79 | });
80 |
81 | if (Platform.isMobile) {
82 | new Setting(el)
83 | .setName("Mobile Only?")
84 | .setDesc("Is this Macro Mobile only?")
85 | .addToggle(cb => {
86 | cb.setDisabled(this.editing);
87 | cb.setValue(command.mobileOnly)
88 | cb.onChange((value) => {
89 | this.command.mobileOnly = value;
90 | this.mobileOnly = value;
91 | })
92 | });
93 | }
94 |
95 | new Setting(el)
96 | .setName("Delay")
97 | .setDesc("Specify a Delay between every Command.")
98 | .addSlider(cb => {
99 | cb.setDisabled(this.editing);
100 | cb.setDynamicTooltip()
101 | .setLimits(10, 2000, 10)
102 | .setValue(this.delay)
103 | .onChange(value => {
104 | this.delay = value;
105 | });
106 | });
107 |
108 | new Setting(el)
109 | .setName("Add Command")
110 | .setDesc("Add a Command to your Macro.")
111 | .addButton(cb => {
112 | cb.setButtonText("+")
113 | .onClick(() => {
114 | new CommandSuggester(this.plugin).open()
115 | })
116 | });
117 |
118 | const commandsEl = el.createDiv({ cls: "M-commands" })
119 | this.coms.forEach(c => {
120 | new Setting(commandsEl)
121 | //@ts-ignore
122 | .setName(this.app.commands.commands[c].name)
123 | .addButton(cb => {
124 | cb.setIcon("trash")
125 | .onClick(() => {
126 | this.coms.remove(c);
127 | this.display();
128 | })
129 | });
130 | });
131 |
132 | const btnDiv = el.createDiv({ cls: "M-flex-center" })
133 | if (this.editing) {
134 | const btn = createEl("button", { text: "Finish" })
135 | btnDiv.appendChild(btn);
136 | btn.addEventListener("click", () => {
137 | const c = this.command as Command;
138 | c.callback = async () => {
139 | for (let i = 0; i < this.coms.length; i++) {
140 | //@ts-ignore
141 | this.plugin.app.commands.executeCommandById(this.coms[i]);
142 | await wait(this.delay);
143 | }
144 | }
145 | dispatchEvent(new CustomEvent("M-macroAdded", {
146 | detail: {
147 | icon: this.command.icon,
148 | mobileOnly: this.mobileOnly,
149 | command: c,
150 | delay: this.delay,
151 | commands: this.coms,
152 | name: this.name,
153 | wasEdited: this.editing,
154 | }
155 | }));
156 | this.close();
157 | });
158 | } else {
159 | if (this.coms.length >= 2 && command.name && command.icon) {
160 | const cbtn = createEl("button", { text: "Create Macro" })
161 | btnDiv.appendChild(cbtn);
162 | cbtn.addEventListener("click", () => {
163 | this.addCommand();
164 | });
165 | }
166 | const btn = createEl("button", { text: "Cancel" })
167 | btnDiv.appendChild(btn);
168 | btn.addEventListener("click", () => {
169 | this.close();
170 | });
171 | }
172 | }
173 |
174 | addCommand() {
175 | const c = this.command as Command;
176 | c.callback = async () => {
177 | for (let i = 0; i < this.coms.length; i++) {
178 | //@ts-ignore
179 | this.plugin.app.commands.executeCommandById(this.coms[i]);
180 | await wait(this.delay);
181 | }
182 | }
183 | this.plugin.addCommand(c);
184 | dispatchEvent(new CustomEvent("M-macroAdded", {
185 | detail: {
186 | icon: this.command.icon,
187 | mobileOnly: this.mobileOnly,
188 | command: c,
189 | delay: this.delay,
190 | commands: this.coms,
191 | name: this.name,
192 | wasEdited: this.editing,
193 | }
194 | }));
195 | this.close();
196 | }
197 |
198 | }
--------------------------------------------------------------------------------
/src/ui/settingsTab.ts:
--------------------------------------------------------------------------------
1 | import { PluginSettingTab, Setting, Notice } from "obsidian";
2 | import MacroPlugin from "src/main";
3 | import MacroCreatorModal from "./macroModal";
4 |
5 | export default class MacroSettingsTab extends PluginSettingTab {
6 | plugin: MacroPlugin;
7 |
8 | constructor(plugin: MacroPlugin) {
9 | super(plugin.app, plugin);
10 | this.plugin = plugin;
11 | addEventListener("M-macroAdded", async (e: CustomEvent) => {
12 | if (e.detail.wasEdited) {
13 | console.log("")
14 | const ids: string[] = [];
15 | e.detail.commands.forEach((element: string) => {
16 | ids.push(element);
17 | });
18 | let m = this.plugin.settings.macros.find((m) => m.name === e.detail.name.replace(/Macro Plugin: /g, ""));
19 | console.log(m);
20 | m = {
21 | icon: e.detail.icon,
22 | mobileOnly: e.detail.mobileOnly,
23 | commandID: e.detail.command.id,
24 | commands: ids,
25 | delay: e.detail.delay,
26 | name: e.detail.name,
27 | };
28 | await this.plugin.saveSettings();
29 | this.display();
30 | } else {
31 | const ids: string[] = [];
32 | e.detail.commands.forEach((element: string) => {
33 | ids.push(element);
34 | });
35 | this.plugin.settings.macros.push({
36 | mobileOnly: e.detail.mobileOnly,
37 | icon: e.detail.icon,
38 | commandID: e.detail.command.id,
39 | commands: ids,
40 | delay: e.detail.delay,
41 | name: e.detail.name,
42 | });
43 | await this.plugin.saveSettings();
44 | this.display();
45 | }
46 | });
47 | }
48 |
49 |
50 | display(): void {
51 | let { containerEl } = this;
52 |
53 | containerEl.empty();
54 |
55 | containerEl.createEl('h2', { text: 'Macro Plugin Settings' });
56 |
57 | new Setting(containerEl)
58 | .setName("Add new Macro")
59 | .setDesc("Create a new Group of Commands to execute one after another.")
60 | .addButton(cb => {
61 | cb.setButtonText("+")
62 | .onClick(() => {
63 | new MacroCreatorModal(this.plugin).open();
64 | })
65 | })
66 |
67 | this.plugin.settings.macros.forEach(macro => {
68 | let dsc = "";
69 | macro.commands.forEach((c, i) => {
70 | //@ts-ignore
71 | dsc += this.app.commands.commands[c].name;
72 | if (i != macro.commands.length - 1) {
73 | dsc += ", "
74 | } else {
75 | dsc += " | "
76 | }
77 | });
78 | dsc += `(Delay: ${macro.delay})`
79 | new Setting(containerEl)
80 | .setName(macro.name)
81 | .setDesc(dsc)
82 | // .addButton(bt => {
83 | // bt.setButtonText("Edit");
84 | // bt.onClick(() => {
85 | // new MacroCreatorModal(this.plugin, macro).open();
86 | // });
87 | // })
88 | .addExtraButton(bt => {
89 | bt.setIcon("trash");
90 | bt.onClick(async () => {
91 | this.plugin.settings.macros.remove(macro);
92 | this.display();
93 | new Notice("You will need to restart Obsidian to fully remove the Macro.")
94 | await this.plugin.saveSettings();
95 | })
96 | });
97 | });
98 |
99 | new Setting(containerEl)
100 | .setName('Donate')
101 | .setDesc('If you like this Plugin, consider donating to support continued development:')
102 | .setClass("AT-extra")
103 | .addButton((bt) => {
104 | bt.buttonEl.outerHTML = `
`;
105 | });
106 | }
107 | }
--------------------------------------------------------------------------------
/src/util.ts:
--------------------------------------------------------------------------------
1 | export async function wait(delay: number) {
2 | return new Promise(resolve => setTimeout(resolve, delay));
3 | }
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | .M-icon {
2 | transform: translateY(3px);
3 | margin-right: 8px;
4 | }
5 |
6 | .M-icon-container{
7 | display: flex;
8 | }
9 |
10 | .M-commands {
11 | background-color: var(--background-secondary);
12 | margin: 1rem;
13 | padding: 1rem 1rem 0px 1rem;
14 | border-radius: 0.8rem;
15 | }
16 |
17 | .M-flex-center {
18 | display: flex;
19 | place-content: center;
20 | }
21 |
22 | a[href="https://www.buymeacoffee.com/phibr0"] > img {
23 | height: 2.2em;
24 | }
25 |
26 | a[href="https://www.buymeacoffee.com/phibr0"]{
27 | transform: translate(0, 5%);
28 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "inlineSourceMap": true,
5 | "inlineSources": true,
6 | "module": "ESNext",
7 | "target": "es6",
8 | "allowJs": true,
9 | "noImplicitAny": true,
10 | "moduleResolution": "node",
11 | "importHelpers": true,
12 | "lib": [
13 | "dom",
14 | "es5",
15 | "scripthost",
16 | "es2015"
17 | ]
18 | },
19 | "include": [
20 | "**/*.ts"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/versions.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0.1": "0.9.12",
3 | "1.0.0": "0.9.7"
4 | }
5 |
--------------------------------------------------------------------------------