Skip to content

Commit

Permalink
feat: New Agenda view that replaces the existing day view. Clicking a…
Browse files Browse the repository at this point in the history
… day will now open a synced Agenda view that can be placed wherever you like.
  • Loading branch information
valentine195 committed Apr 11, 2024
1 parent e6694d1 commit d9e92d1
Show file tree
Hide file tree
Showing 10 changed files with 338 additions and 181 deletions.
12 changes: 12 additions & 0 deletions src/@types/obsidian-ext.d.ts
Expand Up @@ -67,5 +67,17 @@ declare module "obsidian" {
name: "calendarium-settings-external-load",
callback: () => any
): EventRef;

trigger(
name: "calendarium:view-parent:change-calendar",
data: { parent: string; calendar: string }
): void;
on(
name: "calendarium:view-parent:change-calendar",
callback: (data: { parent: string; calendar: string }) => any
): EventRef;
}
interface View {
protected close(): void;
}
}
@@ -1,26 +1,34 @@
<script lang="ts">
import { ExtraButtonComponent } from "obsidian";
import Flags from "../Events/Flags.svelte";
import MoonUI from "../Moon.svelte";
import { getTypedContext } from "../../view";
import Flags from "../ui/Events/Flags.svelte";
import MoonUI from "../ui/Moon.svelte";
import { dateString } from "src/utils/functions";
import {
ADD_EVENT,
CALENDAR_SEARCH,
CLOSE,
LEFT,
RIGHT,
setClickableIcon,
setNodeIcon,
} from "src/utils/icons";
import { addEventWithModal } from "src/settings/modals/event/event";
import { derived } from "svelte/store";
import { derived, get, writable } from "svelte/store";
import type { CalendarStore } from "src/stores/calendar.store";
import type Calendarium from "src/main";
import { setTypedContext } from "../view.utils";
import { onDestroy } from "svelte";
const global = getTypedContext("store");
const plugin = getTypedContext("plugin");
const ephemeral = getTypedContext("ephemeralStore");
$: store = $global;
const viewing = derived([$ephemeral.viewing], ([view]) => view!);
export let store: CalendarStore;
export let plugin: Calendarium;
export let parent: string;
setTypedContext("store", writable(store));
setTypedContext("plugin", plugin);
$: ephemeral = store.getEphemeralStore(parent);
$: ephViewing = ephemeral.viewing;
$: {
if (!$ephViewing) {
$ephViewing = { ...get(store.current) };
}
}
$: viewing = derived([ephemeral.viewing], ([view]) => view!);
$: date = dateString($viewing!, $store);
$: yearCalculator = store.yearCalculator;
$: displayedMonth = yearCalculator
Expand All @@ -30,33 +38,33 @@
$: daysBeforeDay = $daysBeforeMonth + $viewing!.day;
$: events = store.getEventsForDate($viewing!);
$: moons = store.moonCache.getItemsOrRecalculate($viewing!);
$: displayDayNumber = $ephemeral.displayDayNumber;
$: displayMoons = $ephemeral.displayMoons;
$: displayDayNumber = ephemeral.displayDayNumber;
$: displayMoons = ephemeral.displayMoons;
const close = (node: HTMLElement) => {
new ExtraButtonComponent(node).setIcon(CLOSE).setTooltip("Close");
};
/* onDestroy(() => {
ephemeral.viewing.set(null);
}); */
</script>

<div class="day-view">
<hr />
<div class="nav">
<div
use:setClickableIcon={CALENDAR_SEARCH}
aria-label="Reveal on Calendar"
on:click={() => {
$ephemeral.displayDate($viewing);
}}
/>
<div style="flex: 1;">
<div
use:setClickableIcon={CALENDAR_SEARCH}
aria-label="Reveal on Calendar"
on:click={() => {
ephemeral.displayDate($viewing);
}}
/>
</div>
<div class="date">
<div
class="arrow"
use:setClickableIcon={LEFT}
aria-label="Previous"
on:click={() => {
$ephemeral.goToPreviousDay();

$ephemeral.displayDate($viewing);
ephemeral.goToPreviousDay();
ephemeral.displayDate($viewing);
}}
></div>

Expand All @@ -75,18 +83,12 @@
use:setClickableIcon={RIGHT}
aria-label="Next"
on:click={() => {
$ephemeral.goToNextDay();
$ephemeral.displayDate($viewing);
ephemeral.goToNextDay();
ephemeral.displayDate($viewing);
}}
></div>
</div>
<!-- <div class="actions">
<div
use:event
on:click={() => addEventWithModal(plugin, $store, $viewing)}
/>
</div> -->
<div use:close on:click={() => $ephemeral.viewing.set(null)} />
<div style="flex: 1;" />
</div>

<div class="context">
Expand Down Expand Up @@ -119,9 +121,6 @@
gap: 0.5rem;
min-height: 300px;
}
hr {
margin: 0.5em 0;
}
.nav {
display: flex;
justify-content: space-between;
Expand Down
73 changes: 66 additions & 7 deletions src/calendar/codeblock.ts
Expand Up @@ -7,29 +7,76 @@ import {
type EditorSuggestTriggerInfo,
TFile,
parseYaml,
type MarkdownPostProcessorContext,
MarkdownRenderChild,
Notice,
} from "obsidian";
import type { CalendariumCodeBlockParameters } from "src/@types";
import Calendarium from "src/main";

import Ui from "./ui/UI.svelte";
import { nanoid } from "src/utils/functions";
import type { CalendarStore } from "src/stores/calendar.store";
import { ViewType, type ViewParent } from "./view.types";
export class CodeBlockService extends Component {
constructor(public plugin: Calendarium) {
super();
}

onload(): void {
this.plugin.registerMarkdownCodeBlockProcessor(
"calendarium",
(source, el, ctx) => {
this.postProcess(source, el);
this.postProcess(source, el, ctx);
}
);
this.plugin.registerEditorSuggest(
new CalendariumEditorSuggester(this.plugin)
);
}
postProcess(source: string, el: HTMLElement) {
postProcess(
source: string,
el: HTMLElement,
ctx: MarkdownPostProcessorContext
) {
ctx.addChild(new CodeBlockContainer(this.plugin, source, el));
}
}

class CodeBlockContainer extends MarkdownRenderChild implements ViewParent {
ui: Ui;
constructor(
public plugin: Calendarium,
public source: string,
containerEl: HTMLElement
) {
super(containerEl);
}
getViewType: () => string = () => ViewType.Calendarium;
switchCalendar(calendar: string): void {
const newStore = this.plugin.getStore(calendar);
if (!newStore) {
new Notice("There was an issue opening that calendar.");
throw new Error("Could not find a calendar by that name");
}
this.store = newStore;
this.calendar = calendar;

this.ui.$set({ store: this.store });

this.plugin.app.workspace.requestSaveLayout();
this.plugin.app.workspace.trigger(
"calendarium:view-parent:change-calendar",
{ parent: this.id, calendar }
);
}
child: string | null;
id: string = nanoid(12);
calendar: string;
store: CalendarStore;
onload(): void {
const params: CalendariumCodeBlockParameters =
parseYaml(source ?? "") ?? {};
parseYaml(this.source ?? "") ?? {};
let name = params.calendar ?? this.plugin.defaultCalendar.name;
let calendar = this.plugin.calendars.find((c) => c.name === name);
if (!calendar) {
Expand All @@ -38,21 +85,33 @@ export class CodeBlockService extends Component {

const store = this.plugin.getStore(calendar.id);
if (!store) {
el.replaceWith(
this.containerEl.replaceWith(
createEl("code", {
text: "No calendar by that name was found.",
})
);
return;
}
new Ui({
target: el,
this.store = store;
this.calendar = calendar.id;

this.ui = new Ui({
target: this.containerEl,
props: {
store,
store: this.store,
view: this,
plugin: this.plugin,
full: false,
},
});
this.plugin.register(() => {
this.ui?.$destroy();
const pre = createEl("pre");
pre.createEl("code", {
text: "Calendarium has been unloaded. Re-enable the plugin to render your calendars.",
});
this.containerEl.replaceWith(pre);
});
}
}

Expand Down
26 changes: 4 additions & 22 deletions src/calendar/ui/Calendar.svelte
@@ -1,9 +1,9 @@
<script lang="ts">
import Nav from "./Nav.svelte";
import Month from "./Month/Month.svelte";
import { ExtraButtonComponent, Menu } from "obsidian";
import { getTypedContext } from "../view";
import DayView from "./Day/DayView.svelte";
import { ExtraButtonComponent } from "obsidian";
import { getTypedContext } from "../view.utils";
import { ViewState } from "src/stores/calendar.store";
import Year from "./Year/Year.svelte";
import Week from "./Week/Week.svelte";
Expand All @@ -29,8 +29,6 @@
$: ephemeralStore = $ephemeral.ephemeralStore;
$: ephemeralStore.subscribe(() => plugin.app.workspace.requestSaveLayout());
$: viewing = $ephemeral.viewing;
const plugin = getTypedContext("plugin");
let otherCalendars = writable(plugin.data.calendars);
Expand All @@ -52,18 +50,7 @@
)) {
menu.addItem((item) =>
item.setTitle(calendar.name).onClick(() => {
const newStore = plugin.getStore(calendar.id);
if (!newStore)
throw new Error(
"Could not find a calendar by that name",
);
global.set(newStore);
ephemeral.set(newStore.ephemeralStore);
if (view) {
view.store = newStore;
view.calendar = calendar.id;
plugin.app.workspace.requestSaveLayout();
}
view.switchCalendar(calendar.id);
}),
);
}
Expand Down Expand Up @@ -113,13 +100,8 @@
dayArray={weekForDay}
{weekNumber}
/>
{:else if $viewState == ViewState.Day}
<DayView />
{/if}
</div>
{#if $viewing}
<DayView />
{/if}
</div>
{/key}

Expand Down
13 changes: 10 additions & 3 deletions src/calendar/ui/Day/Day.svelte
@@ -1,6 +1,6 @@
<script lang="ts">
import { MonthStore } from "src/stores/month.store";
import { getTypedContext } from "../../view";
import { ViewType } from "../../view.types";
import Dots from "../Events/Dots.svelte";
import { TFile } from "obsidian";
import type { CalEvent } from "src/@types";
Expand All @@ -14,13 +14,16 @@
} from "src/schemas/calendar/timespans";
import CalendariumMenu from "src/utils/menu";
import { isCalEvent } from "src/events/event.types";
import { openAgendaView } from "src/calendar/view.agenda";
import { getTypedContext } from "src/calendar/view.utils";
export let month: MonthStore;
export let day: DayOrLeapDay;
export let adjacent: boolean;
const plugin = getTypedContext("plugin");
const store = getTypedContext("store");
const view = getTypedContext("view");
const ephemeral = getTypedContext("ephemeralStore");
const full = getTypedContext("full");
$: calendar = $store;
Expand Down Expand Up @@ -110,6 +113,11 @@
}
menu.showAtMouseEvent(evt);
};
const handleClick = () => {
$viewing = { day: day.number, month: $index, year: year.year };
openAgendaView(view);
};
</script>

{#if $viewState == ViewState.Year && adjacent}
Expand All @@ -123,8 +131,7 @@
class:opened
class:today
class:full={$full}
on:click={() =>
($viewing = { day: day.number, month: $index, year: year.year })}
on:click={() => handleClick()}
on:contextmenu={(evt) => {
openMenu(evt);
}}
Expand Down
8 changes: 5 additions & 3 deletions src/calendar/ui/UI.svelte
@@ -1,13 +1,15 @@
<script lang="ts">
import type Calendarium from "src/main";
import Calendar from "./Calendar.svelte";
import CalendariumView, { setTypedContext } from "../view";
import CalendariumView from "../view";
import { writable } from "svelte/store";
import { type CalendarStore } from "src/stores/calendar.store";
import { type ViewParent } from "../view.types";
import { setTypedContext } from "../view.utils";
export let store: CalendarStore | null;
export let plugin: Calendarium;
export let view: CalendariumView | null = null;
export let view: ViewParent;
export let full: boolean;
setTypedContext("plugin", plugin);
setTypedContext("view", view);
Expand All @@ -20,7 +22,7 @@
setTypedContext("store", writable(store));
setTypedContext(
"ephemeralStore",
writable(store.getEphemeralStore()),
writable(store.getEphemeralStore(view.id)),
);
}
}
Expand Down

0 comments on commit d9e92d1

Please sign in to comment.