mysticals 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +51 -7
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createElement } from "react";
|
|
|
5
5
|
import { render } from "ink";
|
|
6
6
|
|
|
7
7
|
// package.json
|
|
8
|
-
var version = "0.
|
|
8
|
+
var version = "0.9.0";
|
|
9
9
|
|
|
10
10
|
// src/client.ts
|
|
11
11
|
import { spawn } from "child_process";
|
|
@@ -277,6 +277,8 @@ var en = {
|
|
|
277
277
|
"notify.changed": "Event changed",
|
|
278
278
|
"notify.cancelled": "Event cancelled",
|
|
279
279
|
"notify.many": { one: "{n} calendar update", other: "{n} calendar updates" },
|
|
280
|
+
"reminder.in": "in {n} min",
|
|
281
|
+
"reminder.now": "starting now",
|
|
280
282
|
// ---- desktop: menus, dialogs, update ----
|
|
281
283
|
"menu.file": "File",
|
|
282
284
|
"menu.newEvent": "New Event",
|
|
@@ -345,12 +347,19 @@ var en = {
|
|
|
345
347
|
"settings.tab.language": "Language",
|
|
346
348
|
"settings.tab.sync": "Sync",
|
|
347
349
|
"settings.tab.privacy": "Privacy",
|
|
350
|
+
"settings.tab.notifications": "Notifications",
|
|
351
|
+
"settings.reminders.label": "Remind me before events",
|
|
352
|
+
"settings.reminders.off": "Off",
|
|
353
|
+
"settings.reminders.min": "{n} min before",
|
|
354
|
+
"settings.reminders.note": "A notification pops up before each event while Mysticals is open, with a button to join the call when the event has a link. Declined, all-day and hidden-calendar events stay silent.",
|
|
348
355
|
"settings.noAccounts": "No accounts yet.",
|
|
349
356
|
"settings.addAccount": "Add account\u2026",
|
|
350
357
|
"settings.theme": "Theme",
|
|
351
358
|
"theme.amber": "Phosphor amber",
|
|
352
359
|
"theme.mono": "Black & White",
|
|
353
360
|
"theme.toon": "Cartoon",
|
|
361
|
+
"theme.cloud": "Cloud",
|
|
362
|
+
"theme.light": "Light",
|
|
354
363
|
"settings.language.auto": "Automatic",
|
|
355
364
|
"settings.language.system": "system: {name}",
|
|
356
365
|
"settings.sync.note": "Accounts sync automatically every 2 minutes and when the app regains focus.",
|
|
@@ -365,6 +374,7 @@ var en = {
|
|
|
365
374
|
"settings.privacy.note": "Mysticals sends two anonymous events: when the app is first installed and when an account is added (provider only). Never emails, server addresses, calendars or events.",
|
|
366
375
|
"settings.privacy.policy": "Privacy policy",
|
|
367
376
|
"settings.privacy.share": "Share anonymous usage stats",
|
|
377
|
+
"settings.donate": "Support on Ko-fi",
|
|
368
378
|
"settings.account.labelFor": "Label for {email}",
|
|
369
379
|
"settings.account.colourFor": "Colour for {email}",
|
|
370
380
|
"settings.account.remove": "Remove",
|
|
@@ -610,6 +620,8 @@ var uk = {
|
|
|
610
620
|
"notify.changed": "\u041F\u043E\u0434\u0456\u044E \u0437\u043C\u0456\u043D\u0435\u043D\u043E",
|
|
611
621
|
"notify.cancelled": "\u041F\u043E\u0434\u0456\u044E \u0441\u043A\u0430\u0441\u043E\u0432\u0430\u043D\u043E",
|
|
612
622
|
"notify.many": { one: "{n} \u0437\u043C\u0456\u043D\u0430 \u0432 \u043A\u0430\u043B\u0435\u043D\u0434\u0430\u0440\u0456", few: "{n} \u0437\u043C\u0456\u043D\u0438 \u0432 \u043A\u0430\u043B\u0435\u043D\u0434\u0430\u0440\u0456", many: "{n} \u0437\u043C\u0456\u043D \u0443 \u043A\u0430\u043B\u0435\u043D\u0434\u0430\u0440\u0456", other: "{n} \u0437\u043C\u0456\u043D\u0438 \u0432 \u043A\u0430\u043B\u0435\u043D\u0434\u0430\u0440\u0456" },
|
|
623
|
+
"reminder.in": "\u0447\u0435\u0440\u0435\u0437 {n} \u0445\u0432",
|
|
624
|
+
"reminder.now": "\u043F\u043E\u0447\u0438\u043D\u0430\u0454\u0442\u044C\u0441\u044F \u0437\u0430\u0440\u0430\u0437",
|
|
613
625
|
// ---- desktop: menus, dialogs, update ----
|
|
614
626
|
"menu.file": "\u0424\u0430\u0439\u043B",
|
|
615
627
|
"menu.newEvent": "\u041D\u043E\u0432\u0430 \u043F\u043E\u0434\u0456\u044F",
|
|
@@ -678,12 +690,19 @@ var uk = {
|
|
|
678
690
|
"settings.tab.language": "\u041C\u043E\u0432\u0430",
|
|
679
691
|
"settings.tab.sync": "\u0421\u0438\u043D\u0445\u0440\u043E\u043D\u0456\u0437\u0430\u0446\u0456\u044F",
|
|
680
692
|
"settings.tab.privacy": "\u041A\u043E\u043D\u0444\u0456\u0434\u0435\u043D\u0446\u0456\u0439\u043D\u0456\u0441\u0442\u044C",
|
|
693
|
+
"settings.tab.notifications": "\u0421\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F",
|
|
694
|
+
"settings.reminders.label": "\u041D\u0430\u0433\u0430\u0434\u0443\u0432\u0430\u0442\u0438 \u043F\u0435\u0440\u0435\u0434 \u043F\u043E\u0434\u0456\u044F\u043C\u0438",
|
|
695
|
+
"settings.reminders.off": "\u0412\u0438\u043C\u043A\u043D\u0435\u043D\u043E",
|
|
696
|
+
"settings.reminders.min": "\u0437\u0430 {n} \u0445\u0432",
|
|
697
|
+
"settings.reminders.note": "\u041F\u043E\u043A\u0438 Mysticals \u0432\u0456\u0434\u043A\u0440\u0438\u0442\u0438\u0439, \u043F\u0435\u0440\u0435\u0434 \u043A\u043E\u0436\u043D\u043E\u044E \u043F\u043E\u0434\u0456\u0454\u044E \u0437\u2019\u044F\u0432\u043B\u044F\u0454\u0442\u044C\u0441\u044F \u0441\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u043D\u044F \u0437 \u043A\u043D\u043E\u043F\u043A\u043E\u044E, \u0449\u043E\u0431 \u043F\u0440\u0438\u0454\u0434\u043D\u0430\u0442\u0438\u0441\u044F \u0434\u043E \u0434\u0437\u0432\u0456\u043D\u043A\u0430, \u044F\u043A\u0449\u043E \u0432 \u043F\u043E\u0434\u0456\u0457 \u0454 \u043F\u043E\u0441\u0438\u043B\u0430\u043D\u043D\u044F. \u0412\u0456\u0434\u0445\u0438\u043B\u0435\u043D\u0456, \u0446\u0456\u043B\u043E\u0434\u0435\u043D\u043D\u0456 \u043F\u043E\u0434\u0456\u0457 \u0442\u0430 \u043F\u043E\u0434\u0456\u0457 \u0437 \u043F\u0440\u0438\u0445\u043E\u0432\u0430\u043D\u0438\u0445 \u043A\u0430\u043B\u0435\u043D\u0434\u0430\u0440\u0456\u0432 \u0431\u0435\u0437 \u0441\u043F\u043E\u0432\u0456\u0449\u0435\u043D\u044C.",
|
|
681
698
|
"settings.noAccounts": "\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0445 \u0437\u0430\u043F\u0438\u0441\u0456\u0432 \u0449\u0435 \u043D\u0435\u043C\u0430\u0454.",
|
|
682
699
|
"settings.addAccount": "\u0414\u043E\u0434\u0430\u0442\u0438 \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441\u2026",
|
|
683
700
|
"settings.theme": "\u0422\u0435\u043C\u0430",
|
|
684
701
|
"theme.amber": "\u0411\u0443\u0440\u0448\u0442\u0438\u043D\u043E\u0432\u0438\u0439 \u043B\u044E\u043C\u0456\u043D\u043E\u0444\u043E\u0440",
|
|
685
702
|
"theme.mono": "\u0427\u043E\u0440\u043D\u043E-\u0431\u0456\u043B\u0430",
|
|
686
703
|
"theme.toon": "\u041C\u0443\u043B\u044C\u0442\u044F\u0448\u043D\u0430",
|
|
704
|
+
"theme.cloud": "\u0425\u043C\u0430\u0440\u0438\u043D\u043A\u0430",
|
|
705
|
+
"theme.light": "\u0421\u0432\u0456\u0442\u043B\u0430",
|
|
687
706
|
"settings.language.auto": "\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E",
|
|
688
707
|
"settings.language.system": "\u0441\u0438\u0441\u0442\u0435\u043C\u043D\u0430: {name}",
|
|
689
708
|
"settings.sync.note": "\u041E\u0431\u043B\u0456\u043A\u043E\u0432\u0456 \u0437\u0430\u043F\u0438\u0441\u0438 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0456\u0437\u0443\u044E\u0442\u044C\u0441\u044F \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E \u043A\u043E\u0436\u043D\u0456 2 \u0445\u0432\u0438\u043B\u0438\u043D\u0438 \u0442\u0430 \u043A\u043E\u043B\u0438 \u0437\u0430\u0441\u0442\u043E\u0441\u0443\u043D\u043E\u043A \u0437\u043D\u043E\u0432\u0443 \u0441\u0442\u0430\u0454 \u0430\u043A\u0442\u0438\u0432\u043D\u0438\u043C.",
|
|
@@ -698,6 +717,7 @@ var uk = {
|
|
|
698
717
|
"settings.privacy.note": "Mysticals \u043D\u0430\u0434\u0441\u0438\u043B\u0430\u0454 \u0434\u0432\u0456 \u0430\u043D\u043E\u043D\u0456\u043C\u043D\u0456 \u043F\u043E\u0434\u0456\u0457: \u043A\u043E\u043B\u0438 \u0437\u0430\u0441\u0442\u043E\u0441\u0443\u043D\u043E\u043A \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E \u0432\u043F\u0435\u0440\u0448\u0435 \u0456 \u043A\u043E\u043B\u0438 \u0434\u043E\u0434\u0430\u043D\u043E \u043E\u0431\u043B\u0456\u043A\u043E\u0432\u0438\u0439 \u0437\u0430\u043F\u0438\u0441 (\u043B\u0438\u0448\u0435 \u0442\u0438\u043F \u0441\u0435\u0440\u0432\u0456\u0441\u0443). \u041D\u0456\u043A\u043E\u043B\u0438 \u043D\u0435 \u043D\u0430\u0434\u0441\u0438\u043B\u0430\u0454 \u0430\u0434\u0440\u0435\u0441\u0438 \u043F\u043E\u0448\u0442\u0438 \u0447\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0456\u0432, \u043A\u0430\u043B\u0435\u043D\u0434\u0430\u0440\u0456 \u0430\u0431\u043E \u043F\u043E\u0434\u0456\u0457.",
|
|
699
718
|
"settings.privacy.policy": "\u041F\u043E\u043B\u0456\u0442\u0438\u043A\u0430 \u043A\u043E\u043D\u0444\u0456\u0434\u0435\u043D\u0446\u0456\u0439\u043D\u043E\u0441\u0442\u0456",
|
|
700
719
|
"settings.privacy.share": "\u041D\u0430\u0434\u0441\u0438\u043B\u0430\u0442\u0438 \u0430\u043D\u043E\u043D\u0456\u043C\u043D\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0443 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043D\u044F",
|
|
720
|
+
"settings.donate": "\u041F\u0456\u0434\u0442\u0440\u0438\u043C\u0430\u0442\u0438 \u043D\u0430 Ko-fi",
|
|
701
721
|
"settings.account.labelFor": "\u041D\u0430\u0437\u0432\u0430 \u0434\u043B\u044F {email}",
|
|
702
722
|
"settings.account.colourFor": "\u041A\u043E\u043B\u0456\u0440 \u0434\u043B\u044F {email}",
|
|
703
723
|
"settings.account.remove": "\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438",
|
|
@@ -2489,6 +2509,10 @@ function mapPeople(vevent, email) {
|
|
|
2489
2509
|
});
|
|
2490
2510
|
return { organizer, attendees, myStatus: attendees.find((a) => a.self)?.status };
|
|
2491
2511
|
}
|
|
2512
|
+
function conferenceOf(vevent) {
|
|
2513
|
+
const urls = [...vevent.getAllProperties("conference"), ...vevent.getAllProperties("x-google-conference")].map((p) => String(p.getFirstValue() ?? "").trim());
|
|
2514
|
+
return urls.find((u) => /^https?:\/\//i.test(u));
|
|
2515
|
+
}
|
|
2492
2516
|
function parseEvents(ics, href, etag, ctx, range) {
|
|
2493
2517
|
const root = parse(ics);
|
|
2494
2518
|
const vevents = root.getAllSubcomponents("vevent");
|
|
@@ -2502,6 +2526,7 @@ function parseEvents(ics, href, etag, ctx, range) {
|
|
|
2502
2526
|
const build = (item, start, end, recurrenceId) => {
|
|
2503
2527
|
const rid = recurrenceId?.toString();
|
|
2504
2528
|
const raw = { href, ics, ...rid ? { recurrenceId: rid } : {} };
|
|
2529
|
+
const conference = conferenceOf(item.component);
|
|
2505
2530
|
return {
|
|
2506
2531
|
id: rid ? `${href}#${rid}` : href,
|
|
2507
2532
|
accountId: ctx.accountId,
|
|
@@ -2512,6 +2537,7 @@ function parseEvents(ics, href, etag, ctx, range) {
|
|
|
2512
2537
|
allDay: start.isDate,
|
|
2513
2538
|
location: item.location || void 0,
|
|
2514
2539
|
description: item.description || void 0,
|
|
2540
|
+
...conference ? { conferenceUrl: conference } : {},
|
|
2515
2541
|
...mapPeople(item.component, ctx.email),
|
|
2516
2542
|
etag,
|
|
2517
2543
|
raw,
|
|
@@ -3780,8 +3806,9 @@ import { addDays as addDays8, differenceInCalendarDays as differenceInCalendarDa
|
|
|
3780
3806
|
// ../../packages/core/src/logic/details.ts
|
|
3781
3807
|
import { addDays as addDays7, isSameDay as isSameDay3, parseISO as parseISO7 } from "date-fns";
|
|
3782
3808
|
var same = (a, b) => !!a && !!b && a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
3809
|
+
var extraEmail = (label, email) => same(email, label) ? void 0 : email;
|
|
3783
3810
|
function ownerLine(calendar, label, email) {
|
|
3784
|
-
return { calendar: same(calendar, label) || same(calendar, email) ? void 0 : calendar, label, email:
|
|
3811
|
+
return { calendar: same(calendar, label) || same(calendar, email) ? void 0 : calendar, label, email: extraEmail(label, email) };
|
|
3785
3812
|
}
|
|
3786
3813
|
function canEdit(e, account, calendar) {
|
|
3787
3814
|
if (!account || !calendar || calendar.readOnly) return false;
|
|
@@ -3846,8 +3873,15 @@ function htmlToText(html) {
|
|
|
3846
3873
|
function meetingUrl(location) {
|
|
3847
3874
|
return location?.match(/https?:\/\/[^\s<>"]+/i)?.[0].replace(/[.,;:!?)\]}'>]+$/, "");
|
|
3848
3875
|
}
|
|
3876
|
+
var CALL_KINDS = ["meet", "zoom", "teams", "video"];
|
|
3877
|
+
function descriptionCallUrl(description) {
|
|
3878
|
+
if (!description) return void 0;
|
|
3879
|
+
const hrefs = [...description.matchAll(/href\s*=\s*["']([^"']+)["']/gi)].map((m) => m[1].replace(/&/g, "&"));
|
|
3880
|
+
const urls = [...hrefs, ...linkify(description.replace(/<[^>]*>/g, " ")).flatMap((p) => p.href ? [p.href] : [])];
|
|
3881
|
+
return urls.find((u) => /^https?:\/\//i.test(u) && CALL_KINDS.includes(linkKind(u)));
|
|
3882
|
+
}
|
|
3849
3883
|
function eventMeetingUrl(e) {
|
|
3850
|
-
return e.conferenceUrl ?? meetingUrl(e.location);
|
|
3884
|
+
return e.conferenceUrl ?? meetingUrl(e.location) ?? descriptionCallUrl(e.description);
|
|
3851
3885
|
}
|
|
3852
3886
|
function locationText(location = "") {
|
|
3853
3887
|
return location.replace(/https?:\/\/[^\s<>"]+/gi, "").replace(/^[\s/|,·-]+|[\s/|,·-]+$/g, "");
|
|
@@ -4795,9 +4829,11 @@ function EventEditor({ event, initialStart, onClose }) {
|
|
|
4795
4829
|
const calendar = calendars.find((c) => c.accountId === form.accountId && c.id === form.calendarId);
|
|
4796
4830
|
const value = (f) => {
|
|
4797
4831
|
switch (f) {
|
|
4798
|
-
case "account":
|
|
4799
|
-
|
|
4800
|
-
|
|
4832
|
+
case "account": {
|
|
4833
|
+
const name = account && [account.label, extraEmail(account.label, account.email)].filter(Boolean).join(" \xB7 ");
|
|
4834
|
+
if (event) return { text: name || form.accountId };
|
|
4835
|
+
return name ? { text: name } : { text: "\u2039 choose account \u203A", dim: true };
|
|
4836
|
+
}
|
|
4801
4837
|
case "calendar":
|
|
4802
4838
|
if (event) return { text: calendar?.name ?? form.calendarId };
|
|
4803
4839
|
if (!form.accountId) return { text: "choose an account first", dim: true };
|
|
@@ -5160,6 +5196,7 @@ function AddCaldav({ onBack, onDone }) {
|
|
|
5160
5196
|
|
|
5161
5197
|
// src/ui/screens/Accounts.tsx
|
|
5162
5198
|
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5199
|
+
var DONATE_URL = "https://ko-fi.com/a1exalexander";
|
|
5163
5200
|
function Accounts({ onClose }) {
|
|
5164
5201
|
const api = useApi();
|
|
5165
5202
|
const { accounts, calendars, loaded, error: loadError } = useDirectory();
|
|
@@ -5403,7 +5440,14 @@ function Accounts({ onClose }) {
|
|
|
5403
5440
|
button("a", "add CalDAV"),
|
|
5404
5441
|
/* @__PURE__ */ jsx12(Button, { k: "esc", label: "close", onPress: onClose })
|
|
5405
5442
|
] }),
|
|
5406
|
-
mode.kind === "list" && /* @__PURE__ */
|
|
5443
|
+
mode.kind === "list" && /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
5444
|
+
/* @__PURE__ */ jsx12(Text10, { color: C.muted, children: "Made in Ukraine \xB7 " }),
|
|
5445
|
+
/* @__PURE__ */ jsxs10(Clickable, { onClick: () => void openUrl(DONATE_URL).catch(() => {
|
|
5446
|
+
}), children: [
|
|
5447
|
+
/* @__PURE__ */ jsx12(Text10, { color: C.muted, children: "Support on Ko-fi: " }),
|
|
5448
|
+
/* @__PURE__ */ jsx12(Text10, { color: C.cyan, underline: true, children: DONATE_URL })
|
|
5449
|
+
] })
|
|
5450
|
+
] })
|
|
5407
5451
|
] });
|
|
5408
5452
|
}
|
|
5409
5453
|
var loopbackPort = (authUrl) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mysticals",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Isolated multi-account calendar for the terminal on macOS, Linux and Windows",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"calendar",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"tsup": "^8.5.1",
|
|
48
48
|
"typescript": "^5.9.3",
|
|
49
49
|
"vitest": "^3.2.7",
|
|
50
|
-
"@mysticals/core": "0.
|
|
50
|
+
"@mysticals/core": "0.9.0"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"dev": "tsup --watch",
|