pull/317/head
Lucas Nogueira 2 years ago
parent 6f65b98697
commit 03c858bc34
No known key found for this signature in database
GPG Key ID: FFEA6C72E73482F1

@ -8,17 +8,20 @@ In the future, this app will be used on Tauri's integration tests.
## Running the example
- Install dependencies and build packages (Run inside of the repository root)
```bash
$ pnpm install
$ pnpm build
```
- Run the app in development mode (Run inside of this folder `examples/api/`)
```bash
$ pnpm tauri dev
```
- Build an run the release app (Run inside of this folder `examples/api/`)
```bash
$ pnpm tauri build
$ ./src-tauri/target/release/app

@ -3,5 +3,5 @@
// SPDX-License-Identifier: MIT
window.__TAURI_ISOLATION_HOOK__ = (payload) => {
return payload
}
return payload;
};

@ -26,11 +26,7 @@
"name": "theme",
"takesValue": true,
"description": "App theme",
"possibleValues": [
"light",
"dark",
"system"
]
"possibleValues": ["light", "dark", "system"]
},
{
"short": "v",
@ -92,14 +88,8 @@
"all": true,
"fs": {
"scope": {
"allow": [
"$APPDATA/db/**",
"$DOWNLOAD/**",
"$RESOURCE/**"
],
"deny": [
"$APPDATA/db/*.stronghold"
]
"allow": ["$APPDATA/db/**", "$DOWNLOAD/**", "$RESOURCE/**"],
"deny": ["$APPDATA/db/*.stronghold"]
}
},
"shell": {
@ -130,28 +120,19 @@
"protocol": {
"asset": true,
"assetScope": {
"allow": [
"$APPDATA/db/**",
"$RESOURCE/**"
],
"deny": [
"$APPDATA/db/*.stronghold"
]
"allow": ["$APPDATA/db/**", "$RESOURCE/**"],
"deny": ["$APPDATA/db/*.stronghold"]
}
},
"http": {
"scope": [
"http://localhost:3003"
]
"scope": ["http://localhost:3003"]
}
},
"windows": [],
"security": {
"csp": {
"default-src": "'self' customprotocol: asset:",
"font-src": [
"https://fonts.gstatic.com"
],
"font-src": ["https://fonts.gstatic.com"],
"img-src": "'self' asset: https://asset.localhost blob: data:",
"style-src": "'unsafe-inline' 'self' https://fonts.googleapis.com"
},

@ -5,7 +5,7 @@
* {
box-sizing: border-box;
font-family: 'Rubik', sans-serif;
font-family: "Rubik", sans-serif;
}
::-webkit-scrollbar {

@ -2,12 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import 'uno.css'
import './app.css'
import App from './App.svelte'
import "uno.css";
import "./app.css";
import App from "./App.svelte";
const app = new App({
target: document.querySelector('#app')
})
target: document.querySelector("#app"),
});
export default app
export default app;

@ -7,43 +7,43 @@ import {
presetIcons,
presetUno,
extractorSvelte,
presetWebFonts
} from 'unocss'
presetWebFonts,
} from "unocss";
export default defineConfig({
theme: {
colors: {
primary: '#FFFFFF',
primaryLighter: '#e9ecef',
darkPrimary: '#1B1B1D',
darkPrimaryLighter: '#242526',
primaryText: '#1C1E21',
darkPrimaryText: '#E3E3E3',
secondaryText: '#858A91',
darkSecondaryText: '#C2C5CA',
accent: '#3578E5',
accentDark: '#306cce',
accentDarker: '#2d66c3',
accentDarkest: '#2554a0',
accentLight: '#538ce9',
accentLighter: '#72a1ed',
accentLightest: '#9abcf2',
accentText: '#FFFFFF',
darkAccent: '#67d6ed',
darkAccentDark: '#49cee9',
darkAccentDarker: '#39cae8',
darkAccentDarkest: '#19b5d5',
darkAccentLight: '#85def1',
darkAccentLighter: '#95e2f2',
darkAccentLightest: '#c2eff8',
darkAccentText: '#1C1E21',
code: '#d6d8da',
codeDark: '#282a2e',
hoverOverlay: 'rgba(0,0,0,.05)',
hoverOverlayDarker: 'rgba(0,0,0,.1)',
darkHoverOverlay: 'hsla(0,0%,100%,.05)',
darkHoverOverlayDarker: 'hsla(0,0%,100%,.1)'
}
primary: "#FFFFFF",
primaryLighter: "#e9ecef",
darkPrimary: "#1B1B1D",
darkPrimaryLighter: "#242526",
primaryText: "#1C1E21",
darkPrimaryText: "#E3E3E3",
secondaryText: "#858A91",
darkSecondaryText: "#C2C5CA",
accent: "#3578E5",
accentDark: "#306cce",
accentDarker: "#2d66c3",
accentDarkest: "#2554a0",
accentLight: "#538ce9",
accentLighter: "#72a1ed",
accentLightest: "#9abcf2",
accentText: "#FFFFFF",
darkAccent: "#67d6ed",
darkAccentDark: "#49cee9",
darkAccentDarker: "#39cae8",
darkAccentDarkest: "#19b5d5",
darkAccentLight: "#85def1",
darkAccentLighter: "#95e2f2",
darkAccentLightest: "#c2eff8",
darkAccentText: "#1C1E21",
code: "#d6d8da",
codeDark: "#282a2e",
hoverOverlay: "rgba(0,0,0,.05)",
hoverOverlayDarker: "rgba(0,0,0,.1)",
darkHoverOverlay: "hsla(0,0%,100%,.05)",
darkHoverOverlayDarker: "hsla(0,0%,100%,.1)",
},
},
preflights: [
{
@ -59,7 +59,7 @@ export default defineConfig({
code {
font-size: ${theme.fontSize.xs[0]};
font-family: ${theme.fontFamily.mono};
border-radius: ${theme.borderRadius['DEFAULT']};
border-radius: ${theme.borderRadius["DEFAULT"]};
background-color: ${theme.colors.code};
}
@ -71,8 +71,8 @@ export default defineConfig({
.dark code {
background-color: ${theme.colors.codeDark};
}
`
}
`,
},
],
shortcuts: {
btn: `select-none outline-none shadow-md p-2 rd-1 text-primaryText border-none font-400 dark:font-600
@ -86,20 +86,20 @@ export default defineConfig({
note: `decoration-none flex-inline items-center relative p-2 rd-1
border-l-4 border-accent dark:border-darkAccent
bg-accent/10 dark:bg-darkAccent/10`,
'note-red':
'note bg-red-700/10 dark:bg-red-700/10 after:bg-red-700 dark:after:bg-red-700',
"note-red":
"note bg-red-700/10 dark:bg-red-700/10 after:bg-red-700 dark:after:bg-red-700",
input:
'h-10 flex items-center outline-none border-none p-2 rd-1 shadow-md bg-primaryLighter dark:bg-darkPrimaryLighter text-primaryText dark:text-darkPrimaryText'
"h-10 flex items-center outline-none border-none p-2 rd-1 shadow-md bg-primaryLighter dark:bg-darkPrimaryLighter text-primaryText dark:text-darkPrimaryText",
},
presets: [
presetUno(),
presetIcons(),
presetWebFonts({
fonts: {
sans: 'Rubik',
mono: ['Fira Code', 'Fira Mono:400,700']
}
})
sans: "Rubik",
mono: ["Fira Code", "Fira Mono:400,700"],
},
}),
],
extractors: [extractorSvelte]
})
extractors: [extractorSvelte],
});

@ -2,14 +2,18 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import { defineConfig } from 'vite'
import Unocss from 'unocss/vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { internalIpV4 } from 'internal-ip'
import { defineConfig } from "vite";
import Unocss from "unocss/vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { internalIpV4 } from "internal-ip";
// https://vitejs.dev/config/
export default defineConfig(async ({ command, mode }) => {
const host = process.env.TAURI_PLATFORM === 'android' || process.env.TAURI_PLATFORM === 'ios' ? (await internalIpV4()) : 'localhost'
const host =
process.env.TAURI_PLATFORM === "android" ||
process.env.TAURI_PLATFORM === "ios"
? await internalIpV4()
: "localhost";
return {
plugins: [Unocss(), svelte()],
build: {
@ -17,22 +21,22 @@ export default defineConfig(async ({ command, mode }) => {
output: {
entryFileNames: `assets/[name].js`,
chunkFileNames: `assets/[name].js`,
assetFileNames: `assets/[name].[ext]`
}
}
assetFileNames: `assets/[name].[ext]`,
},
},
},
server: {
host: '0.0.0.0',
host: "0.0.0.0",
port: 5173,
strictPort: true,
hmr: {
protocol: 'ws',
protocol: "ws",
host,
port: 5183
port: 5183,
},
fs: {
allow: ['.', '../../tooling/api/dist']
}
}
}
})
allow: [".", "../../tooling/api/dist"],
},
},
};
});

@ -24,7 +24,7 @@
* @module
*/
import { invoke, transformCallback } from '@tauri-apps/api/tauri'
import { invoke, transformCallback } from "@tauri-apps/api/tauri";
/**
* Options to send a notification.
@ -35,54 +35,54 @@ interface Options {
/**
* The notification identifier to reference this object later. Must be a 32-bit integer.
*/
id?: number
id?: number;
/**
* Identifier of the {@link Channel} that deliveres this notification.
*
* If the channel does not exist, the notification won't fire.
* Make sure the channel exists with {@link listChannels} and {@link createChannel}.
*/
channelId?: string
channelId?: string;
/**
* Notification title.
*/
title: string
title: string;
/**
* Optional notification body.
* */
body?: string
body?: string;
/**
* Schedule this notification to fire on a later time or a fixed interval.
*/
schedule?: Schedule
schedule?: Schedule;
/**
* Multiline text.
* Changes the notification style to big text.
* Cannot be used with `inboxLines`.
*/
largeBody?: string
largeBody?: string;
/**
* Detail text for the notification with `largeBody`, `inboxLines` or `groupSummary`.
*/
summary?: string
summary?: string;
/**
* Defines an action type for this notification.
*/
actionTypeId?: string
actionTypeId?: string;
/**
* Identifier used to group multiple notifications.
*
* https://developer.apple.com/documentation/usernotifications/unmutablenotificationcontent/1649872-threadidentifier
*/
group?: string
group?: string;
/**
* Instructs the system that this notification is the summary of a group on Android.
*/
groupSummary?: boolean
groupSummary?: boolean;
/**
* The sound resource name. Only available on mobile.
*/
sound?: string
sound?: string;
/**
* List of lines to add to the notification.
* Changes the notification style to inbox.
@ -90,31 +90,31 @@ interface Options {
*
* Only supports up to 5 lines.
*/
inboxLines?: string[]
inboxLines?: string[];
/**
* Notification icon.
*
* On Android the icon must be placed in the app's `res/drawable` folder.
*/
icon?: string
icon?: string;
/**
* Notification large icon (Android).
*
* The icon must be placed in the app's `res/drawable` folder.
*/
largeIcon?: string
largeIcon?: string;
/**
* Icon color on Android.
*/
iconColor?: string
iconColor?: string;
/**
* Notification attachments.
*/
attachments?: Attachment[]
attachments?: Attachment[];
/**
* Extra payload to store in the notification.
*/
extra?: { [key: string]: unknown }
extra?: { [key: string]: unknown };
/**
* If true, the notification cannot be dismissed by the user on Android.
*
@ -122,29 +122,29 @@ interface Options {
* It is typically used to indicate a background task that is pending (e.g. a file download)
* or the user is engaged with (e.g. playing music).
*/
ongoing?: boolean
ongoing?: boolean;
/**
* Automatically cancel the notification when the user clicks on it.
*/
autoCancel?: boolean
autoCancel?: boolean;
/**
* Changes the notification presentation to be silent on iOS (no badge, no sound, not listed).
*/
silent?: boolean
silent?: boolean;
/**
* Notification visibility.
*/
visibility?: Visibility
visibility?: Visibility;
/**
* Sets the number of items this notification represents on Android.
*/
number?: number
number?: number;
}
type ScheduleInterval = {
year?: number
month?: number
day?: number
year?: number;
month?: number;
day?: number;
/**
* 1 - Sunday
* 2 - Monday
@ -154,61 +154,64 @@ type ScheduleInterval = {
* 6 - Friday
* 7 - Saturday
*/
weekday?: number
hour?: number
minute?: number
second?: number
}
weekday?: number;
hour?: number;
minute?: number;
second?: number;
};
enum ScheduleEvery {
Year = 'Year',
Month = 'Month',
TwoWeeks = 'TwoWeeks',
Week = 'Week',
Day = 'Day',
Hour = 'Hour',
Minute = 'Minute',
Year = "Year",
Month = "Month",
TwoWeeks = "TwoWeeks",
Week = "Week",
Day = "Day",
Hour = "Hour",
Minute = "Minute",
/**
* Not supported on iOS.
*/
Second = 'Second'
Second = "Second",
}
type ScheduleData = {
kind: 'At',
data: {
date: Date
repeating: boolean
}
} | {
kind: 'Interval',
data: ScheduleInterval
} | {
kind: 'Every',
data: {
interval: ScheduleEvery
}
}
type ScheduleData =
| {
kind: "At";
data: {
date: Date;
repeating: boolean;
};
}
| {
kind: "Interval";
data: ScheduleInterval;
}
| {
kind: "Every";
data: {
interval: ScheduleEvery;
};
};
class Schedule {
kind: string
data: unknown
kind: string;
data: unknown;
private constructor(schedule: ScheduleData) {
this.kind = schedule.kind
this.data = schedule.data
this.kind = schedule.kind;
this.data = schedule.data;
}
static at(date: Date, repeating = false) {
return new Schedule({ kind: 'At', data: { date, repeating } })
return new Schedule({ kind: "At", data: { date, repeating } });
}
static interval(interval: ScheduleInterval) {
return new Schedule({ kind: 'Interval', data: interval })
return new Schedule({ kind: "Interval", data: interval });
}
static every(kind: ScheduleEvery) {
return new Schedule({ kind: 'Every', data: { interval: kind } })
return new Schedule({ kind: "Every", data: { interval: kind } });
}
}
@ -217,58 +220,58 @@ class Schedule {
*/
interface Attachment {
/** Attachment identifier. */
id: string
id: string;
/** Attachment URL. Accepts the `asset` and `file` protocols. */
url: string
url: string;
}
interface Action {
id: string
title: string
requiresAuthentication?: boolean
foreground?: boolean
destructive?: boolean
input?: boolean
inputButtonTitle?: string
inputPlaceholder?: string
id: string;
title: string;
requiresAuthentication?: boolean;
foreground?: boolean;
destructive?: boolean;
input?: boolean;
inputButtonTitle?: string;
inputPlaceholder?: string;
}
interface ActionType {
/**
* The identifier of this action type
*/
id: string
id: string;
/**
* The list of associated actions
*/
actions: Action[]
hiddenPreviewsBodyPlaceholder?: string,
customDismissAction?: boolean,
allowInCarPlay?: boolean,
hiddenPreviewsShowTitle?: boolean,
hiddenPreviewsShowSubtitle?: boolean,
actions: Action[];
hiddenPreviewsBodyPlaceholder?: string;
customDismissAction?: boolean;
allowInCarPlay?: boolean;
hiddenPreviewsShowTitle?: boolean;
hiddenPreviewsShowSubtitle?: boolean;
}
interface PendingNotification {
id: number
title?: string
body?: string
schedule: Schedule
id: number;
title?: string;
body?: string;
schedule: Schedule;
}
interface ActiveNotification {
id: number
tag?: string
title?: string
body?: string
group?: string
groupSummary: boolean
data: Record<string, string>
extra: Record<string, unknown>
attachments: Attachment[]
actionTypeId?: string
schedule?: Schedule
sound?: string
id: number;
tag?: string;
title?: string;
body?: string;
group?: string;
groupSummary: boolean;
data: Record<string, string>;
extra: Record<string, unknown>;
attachments: Attachment[];
actionTypeId?: string;
schedule?: Schedule;
sound?: string;
}
enum Importance {
@ -276,25 +279,25 @@ enum Importance {
Min,
Low,
Default,
High
High,
}
enum Visibility {
Secret = -1,
Private,
Public
Public,
}
interface Channel {
id: string
name: string
description?: string
sound?: string
lights?: boolean
lightColor?: string
vibration?: boolean
importance?: Importance
visibility?: Visibility
id: string;
name: string;
description?: string;
sound?: string;
lights?: boolean;
lightColor?: string;
vibration?: boolean;
importance?: Importance;
visibility?: Visibility;
}
/** Possible permission values. */
@ -385,7 +388,7 @@ function sendNotification(options: Options | string): void {
* @since 2.0.0
*/
async function registerActionTypes(types: ActionType[]): Promise<void> {
return invoke('plugin:notification|register_action_types', { types })
return invoke("plugin:notification|register_action_types", { types });
}
/**
@ -402,7 +405,7 @@ async function registerActionTypes(types: ActionType[]): Promise<void> {
* @since 2.0.0
*/
async function pending(): Promise<PendingNotification[]> {
return invoke('plugin:notification|get_pending')
return invoke("plugin:notification|get_pending");
}
/**
@ -419,7 +422,7 @@ async function pending(): Promise<PendingNotification[]> {
* @since 2.0.0
*/
async function cancel(notifications: number[]): Promise<void> {
return invoke('plugin:notification|cancel', { notifications })
return invoke("plugin:notification|cancel", { notifications });
}
/**
@ -436,7 +439,7 @@ async function cancel(notifications: number[]): Promise<void> {
* @since 2.0.0
*/
async function cancelAll(): Promise<void> {
return invoke('plugin:notification|cancel')
return invoke("plugin:notification|cancel");
}
/**
@ -453,7 +456,7 @@ async function cancelAll(): Promise<void> {
* @since 2.0.0
*/
async function active(): Promise<ActiveNotification[]> {
return invoke('plugin:notification|get_active')
return invoke("plugin:notification|get_active");
}
/**
@ -470,7 +473,7 @@ async function active(): Promise<ActiveNotification[]> {
* @since 2.0.0
*/
async function removeActive(notifications: number[]): Promise<void> {
return invoke('plugin:notification|remove_active', { notifications })
return invoke("plugin:notification|remove_active", { notifications });
}
/**
@ -487,7 +490,7 @@ async function removeActive(notifications: number[]): Promise<void> {
* @since 2.0.0
*/
async function removeAllActive(): Promise<void> {
return invoke('plugin:notification|remove_active')
return invoke("plugin:notification|remove_active");
}
/**
@ -511,7 +514,7 @@ async function removeAllActive(): Promise<void> {
* @since 2.0.0
*/
async function createChannel(channel: Channel): Promise<void> {
return invoke('plugin:notification|create_channel', { ...channel })
return invoke("plugin:notification|create_channel", { ...channel });
}
/**
@ -528,7 +531,7 @@ async function createChannel(channel: Channel): Promise<void> {
* @since 2.0.0
*/
async function removeChannel(id: string): Promise<void> {
return invoke('plugin:notification|delete_channel', { id })
return invoke("plugin:notification|delete_channel", { id });
}
/**
@ -545,43 +548,74 @@ async function removeChannel(id: string): Promise<void> {
* @since 2.0.0
*/
async function channels(): Promise<Channel[]> {
return invoke('plugin:notification|getActive')
return invoke("plugin:notification|getActive");
}
class EventChannel {
id: number
unregisterFn: (channel: EventChannel) => Promise<void>
constructor(id: number, unregisterFn: (channel: EventChannel) => Promise<void>) {
this.id = id
this.unregisterFn = unregisterFn
id: number;
unregisterFn: (channel: EventChannel) => Promise<void>;
constructor(
id: number,
unregisterFn: (channel: EventChannel) => Promise<void>
) {
this.id = id;
this.unregisterFn = unregisterFn;
}
toJSON(): string {
return `__CHANNEL__:${this.id}`
return `__CHANNEL__:${this.id}`;
}
async unregister(): Promise<void> {
return this.unregisterFn(this)
return this.unregisterFn(this);
}
}
// TODO: use addPluginListener API on @tauri-apps/api/tauri 2.0.0-alpha.4
async function onNotificationReceived(cb: (notification: Options) => void): Promise<EventChannel> {
const channelId = transformCallback(cb)
const handler = new EventChannel(channelId, (channel) => invoke('plugin:notification|remove_listener', { event: 'notification', channelId: channel.id }))
return invoke('plugin:notification|register_listener', { event: 'notification', handler }).then(() => handler)
async function onNotificationReceived(
cb: (notification: Options) => void
): Promise<EventChannel> {
const channelId = transformCallback(cb);
const handler = new EventChannel(channelId, (channel) =>
invoke("plugin:notification|remove_listener", {
event: "notification",
channelId: channel.id,
})
);
return invoke("plugin:notification|register_listener", {
event: "notification",
handler,
}).then(() => handler);
}
// TODO: use addPluginListener API on @tauri-apps/api/tauri 2.0.0-alpha.4
async function onAction(cb: (notification: Options) => void): Promise<EventChannel> {
const channelId = transformCallback(cb)
const handler = new EventChannel(channelId, (channel) => invoke('plugin:notification|remove_listener', { event: 'actionPerformed', channelId: channel.id }))
return invoke('plugin:notification|register_listener', { event: 'actionPerformed', handler }).then(() => handler)
async function onAction(
cb: (notification: Options) => void
): Promise<EventChannel> {
const channelId = transformCallback(cb);
const handler = new EventChannel(channelId, (channel) =>
invoke("plugin:notification|remove_listener", {
event: "actionPerformed",
channelId: channel.id,
})
);
return invoke("plugin:notification|register_listener", {
event: "actionPerformed",
handler,
}).then(() => handler);
}
export type { Attachment, Options, Permission, Action, ActionType, PendingNotification, ActiveNotification, Channel }
export type {
Attachment,
Options,
Permission,
Action,
ActionType,
PendingNotification,
ActiveNotification,
Channel,
};
export {
Importance,
@ -599,7 +633,6 @@ export {
createChannel,
removeChannel,
channels,
onNotificationReceived,
onAction
}
onAction,
};

Loading…
Cancel
Save