Skip to content

Commit 725c908

Browse files
zhensherlockcodex
andcommitted
feat(timing): add Timing URL scheme support
Co-Authored-By: Codex <267193182+codex@users.noreply.github.com>
1 parent 23ab7de commit 725c908

21 files changed

Lines changed: 828 additions & 0 deletions

File tree

.changeset/silver-timers-visit.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"protocol-launcher": minor
3+
---
4+
5+
feat(timing): add Timing URL scheme support

apps/docs/.vitepress/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ export default defineConfig({
235235
'en/apps/things.md': 'apps/things.md',
236236
'en/apps/thunder.md': 'apps/thunder.md',
237237
'en/apps/tim.md': 'apps/tim.md',
238+
'en/apps/timing.md': 'apps/timing.md',
238239
'en/apps/timer-plus.md': 'apps/timer-plus.md',
239240
'en/apps/timepage.md': 'apps/timepage.md',
240241
'en/apps/today-habit-tracker.md': 'apps/today-habit-tracker.md',
@@ -528,6 +529,7 @@ export default defineConfig({
528529
{ text: 'Things', link: '/apps/things' },
529530
{ text: 'Thunder', link: '/apps/thunder' },
530531
{ text: 'Tim', link: '/apps/tim' },
532+
{ text: 'Timing', link: '/apps/timing' },
531533
{ text: 'Timer+', link: '/apps/timer-plus' },
532534
{ text: 'Timepage', link: '/apps/timepage' },
533535
{ text: 'Today Habit Tracker', link: '/apps/today-habit-tracker' },
@@ -827,6 +829,7 @@ export default defineConfig({
827829
{ text: 'Things', link: '/apps/things' },
828830
{ text: 'Thunder', link: '/apps/thunder' },
829831
{ text: 'Tim', link: '/apps/tim' },
832+
{ text: 'Timing', link: '/apps/timing' },
830833
{ text: 'Timer+', link: '/apps/timer-plus' },
831834
{ text: 'Timepage', link: '/apps/timepage' },
832835
{ text: 'Today Habit Tracker', link: '/apps/today-habit-tracker' },
@@ -1091,6 +1094,7 @@ export default defineConfig({
10911094
{ text: 'Things', link: '/zh/apps/things' },
10921095
{ text: 'Thunder', link: '/zh/apps/thunder' },
10931096
{ text: 'Tim', link: '/zh/apps/tim' },
1097+
{ text: 'Timing', link: '/zh/apps/timing' },
10941098
{ text: 'Timer+', link: '/zh/apps/timer-plus' },
10951099
{ text: 'Timepage', link: '/zh/apps/timepage' },
10961100
{ text: 'Today Habit Tracker', link: '/zh/apps/today-habit-tracker' },

apps/docs/.vitepress/constants/app-logos.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ export const appLogoFiles = {
215215
things: 'things.png',
216216
thunder: 'thunder.svg',
217217
tim: 'tim-time-tracker.webp',
218+
timing: 'timing.webp',
218219
'timer-plus': 'timer-plus.webp',
219220
timepage: 'moleskine-planner.webp',
220221
'today-habit-tracker': 'today-habit-tracker.webp',

apps/docs/en/apps/timing.md

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
---
2+
layout: doc
3+
---
4+
5+
<script setup lang="ts">
6+
import { ref, computed } from 'vue';
7+
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
8+
import {
9+
createTimeEntry,
10+
editTimeEntry,
11+
selectProjects,
12+
startTimer,
13+
stopTimer,
14+
} from 'protocol-launcher/timing';
15+
import { SelectInstallationMethod } from '../../.vitepress/components';
16+
17+
const currentMethod = ref('On-Demand');
18+
const importPath = computed(() => currentMethod.value === 'On-Demand' ? 'protocol-launcher/timing' : 'protocol-launcher');
19+
20+
const startTimerParams = {
21+
title: 'Some title',
22+
notes: 'Some\nnotes',
23+
project: 'Work',
24+
estimatedDuration: 600,
25+
startDate: '2022-04-01T12:00:00Z',
26+
startImmediately: false,
27+
center: true,
28+
};
29+
30+
const createTimeEntryParams = {
31+
title: 'Some title',
32+
notes: 'Some\nnotes',
33+
project: 'Work',
34+
startDate: '2022-04-01T12:00:00Z',
35+
endDate: '2022-04-01T12:30:00Z',
36+
createImmediately: false,
37+
center: true,
38+
};
39+
40+
const selectProjectsParams = {
41+
projects: ['ProjectA', 'ProjectB'],
42+
};
43+
</script>
44+
45+
# Timing
46+
47+
[Timing](https://timingapp.com/) is an automatic time tracking app for Mac. **Protocol Launcher** allows you to generate official URL scheme links for Timing.
48+
49+
## Usage
50+
51+
There are two ways to use this library:
52+
53+
- On-Demand import from subpaths enables tree-shaking and keeps bundles small.
54+
- Full Import from the root package is convenient but includes all app modules.
55+
56+
Pick On-Demand for production builds; Full Import is fine for quick scripts or demos.
57+
58+
<SelectInstallationMethod v-model="currentMethod" />
59+
60+
## Notes
61+
62+
Timing's official URL scheme page says these URLs require at least Timing Expert. It also uses different schemes depending on the target: `timing2helper://` for tracker app actions and `timing2://` for the main Timing app.
63+
64+
This module exposes only the documented URL forms: `startTimer`, `stopTimer`, `createTimeEntry`, `editTimeEntry/<time-entry-id>`, and `selectProjects/<project-name-or-id>`.
65+
66+
## URL Methods
67+
68+
### Start Timer
69+
70+
Generate the documented URL that starts a timer in the Timing tracker app. Set `startImmediately` to `false` when you want Timing to present the dialogue first.
71+
72+
```ts-vue [{{currentMethod}}]
73+
import { {{ currentMethod === 'On-Demand' ? 'startTimer' : 'timing' }} } from '{{ importPath }}'
74+
75+
const url = {{currentMethod === 'On-Demand' ? '' : 'timing.'}}startTimer({
76+
title: 'Some title',
77+
notes: 'Some\nnotes',
78+
project: 'Work',
79+
estimatedDuration: 600,
80+
startDate: '2022-04-01T12:00:00Z',
81+
startImmediately: false,
82+
center: true,
83+
})
84+
```
85+
86+
<div class="flex justify-center">
87+
<VPLink :href="startTimer(startTimerParams)" target="_self">
88+
Start Timing Timer
89+
</VPLink>
90+
</div>
91+
92+
### Stop Timer
93+
94+
Generate the documented URL that stops the currently running timer, if available. `hideNotification` suppresses the notification when the timer is stopped.
95+
96+
```ts-vue [{{currentMethod}}]
97+
import { {{ currentMethod === 'On-Demand' ? 'stopTimer' : 'timing' }} } from '{{ importPath }}'
98+
99+
const url = {{currentMethod === 'On-Demand' ? '' : 'timing.'}}stopTimer({
100+
hideNotification: true,
101+
})
102+
```
103+
104+
### Create Time Entry
105+
106+
Generate the documented URL that creates a new time entry in the Timing tracker app.
107+
108+
```ts-vue [{{currentMethod}}]
109+
import { {{ currentMethod === 'On-Demand' ? 'createTimeEntry' : 'timing' }} } from '{{ importPath }}'
110+
111+
const url = {{currentMethod === 'On-Demand' ? '' : 'timing.'}}createTimeEntry({
112+
title: 'Some title',
113+
notes: 'Some\nnotes',
114+
project: 'Work',
115+
startDate: '2022-04-01T12:00:00Z',
116+
endDate: '2022-04-01T12:30:00Z',
117+
createImmediately: false,
118+
center: true,
119+
})
120+
```
121+
122+
<div class="flex justify-center">
123+
<VPLink :href="createTimeEntry(createTimeEntryParams)" target="_self">
124+
Create Timing Entry
125+
</VPLink>
126+
</div>
127+
128+
Timing documents `createImmediately` as available only when at least `startDate`, `endDate`, and one of `title` or `project` are provided. `center` and `obtainFocus` are only available when `createImmediately` is not true.
129+
130+
### Edit Time Entry
131+
132+
Generate the documented URL that presents a dialogue to edit a time entry by ID. Timing also documents `latest` for editing the most recent time entry.
133+
134+
```ts-vue [{{currentMethod}}]
135+
import { {{ currentMethod === 'On-Demand' ? 'editTimeEntry' : 'timing' }} } from '{{ importPath }}'
136+
137+
const url = {{currentMethod === 'On-Demand' ? '' : 'timing.'}}editTimeEntry({
138+
id: 'latest',
139+
})
140+
```
141+
142+
### Select Projects
143+
144+
Generate the documented URL that selects projects in the sidebar of the main Timing app. Omit `projects` to select "All Activities".
145+
146+
```ts-vue [{{currentMethod}}]
147+
import { {{ currentMethod === 'On-Demand' ? 'selectProjects' : 'timing' }} } from '{{ importPath }}'
148+
149+
const url = {{currentMethod === 'On-Demand' ? '' : 'timing.'}}selectProjects({
150+
projects: ['ProjectA', 'ProjectB'],
151+
})
152+
```
153+
154+
<div class="flex justify-center">
155+
<VPLink :href="selectProjects(selectProjectsParams)" target="_self">
156+
Select Timing Projects
157+
</VPLink>
158+
</div>
159+
160+
```ts-vue [{{currentMethod}}]
161+
import { {{ currentMethod === 'On-Demand' ? 'selectProjects' : 'timing' }} } from '{{ importPath }}'
162+
163+
const url = {{currentMethod === 'On-Demand' ? '' : 'timing.'}}selectProjects()
164+
```
165+
166+
## Generated URLs
167+
168+
```ts
169+
startTimer({
170+
title: 'Some title',
171+
notes: 'Some\nnotes',
172+
project: 'Work',
173+
estimatedDuration: 600,
174+
startDate: '2022-04-01T12:00:00Z',
175+
startImmediately: false,
176+
center: true,
177+
})
178+
// => 'timing2helper://startTimer?title=Some%20title&notes=Some%0Anotes&project=Work&estimatedDuration=600&startDate=2022-04-01T12:00:00Z&startImmediately=false&center=true'
179+
180+
stopTimer({ hideNotification: true })
181+
// => 'timing2helper://stopTimer?hideNotification=true'
182+
183+
createTimeEntry({
184+
title: 'Some title',
185+
notes: 'Some\nnotes',
186+
project: 'Work',
187+
startDate: '2022-04-01T12:00:00Z',
188+
endDate: '2022-04-01T12:30:00Z',
189+
createImmediately: false,
190+
center: true,
191+
})
192+
// => 'timing2helper://createTimeEntry?title=Some%20title&notes=Some%0Anotes&project=Work&startDate=2022-04-01T12:00:00Z&endDate=2022-04-01T12:30:00Z&createImmediately=false&center=true'
193+
194+
editTimeEntry({ id: 'latest' })
195+
// => 'timing2helper://editTimeEntry/latest'
196+
197+
selectProjects({ projects: ['ProjectA', 'ProjectB'] })
198+
// => 'timing2://selectProjects/ProjectA/ProjectB'
199+
200+
selectProjects()
201+
// => 'timing2://selectProjects'
202+
```
203+
204+
## Official Documentation
205+
206+
- [Timing URL Scheme Support](https://timingapp.com/help/url-schemes)

apps/docs/en/guide/getting-started.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ For detailed usage instructions for each application, please refer to their resp
334334
- [Things](../apps/things.md)
335335
- [Thunder](../apps/thunder.md)
336336
- [Tim](../apps/tim.md)
337+
- [Timing](../apps/timing.md)
337338
- [Timer+](../apps/timer-plus.md)
338339
- [Timepage](../apps/timepage.md)
339340
- [Today Habit Tracker](../apps/today-habit-tracker.md)

apps/docs/en/guide/what-is-it.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ Currently, we support the following applications:
243243
- [Things](../apps/things.md)
244244
- [Thunder](../apps/thunder.md)
245245
- [Tim](../apps/tim.md)
246+
- [Timing](../apps/timing.md)
246247
- [Timer+](../apps/timer-plus.md)
247248
- [Timepage](../apps/timepage.md)
248249
- [Today Habit Tracker](../apps/today-habit-tracker.md)
8.19 KB
Loading

0 commit comments

Comments
 (0)