2025-03-24 02:38:44 +00:00
import { App , PluginSettingTab , Setting , Notice } from 'obsidian' ;
import TickTickPlugin from './main' ;
export interface TickTickSettings {
accessToken : string ;
refreshToken? : string ;
2025-03-31 00:45:19 +00:00
tokenExpiry? : number ;
2025-03-24 02:38:44 +00:00
clientId : string ;
clientSecret : string ;
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
redirectUri? : string ;
2025-03-24 02:38:44 +00:00
tempCodeVerifier? : string ;
tempState? : string ;
2026-03-11 23:41:17 +00:00
selectionMode : 'line' | 'paragraph' ;
tagPosition : 'append' | 'prepend' ;
2025-03-24 02:38:44 +00:00
}
export const DEFAULT_SETTINGS : TickTickSettings = {
accessToken : '' ,
clientId : '' ,
2025-03-31 00:45:19 +00:00
clientSecret : '' ,
2026-03-11 23:41:17 +00:00
redirectUri : 'https://ticktick-quick-add-obsidian-6yawfmvnj-mooshs-projects-0635287d.vercel.app' ,
selectionMode : 'line' ,
tagPosition : 'append'
2025-03-24 02:38:44 +00:00
} ;
export class TickTickSettingTab extends PluginSettingTab {
plugin : TickTickPlugin ;
constructor ( app : App , plugin : TickTickPlugin ) {
super ( app , plugin ) ;
this . plugin = plugin ;
}
display ( ) : void {
const { containerEl } = this ;
containerEl . empty ( ) ;
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
if ( this . plugin . settings . accessToken ) {
this . renderConnectedView ( containerEl ) ;
} else {
this . renderSetupView ( containerEl ) ;
}
}
private renderSetupView ( containerEl : HTMLElement ) : void {
containerEl . createEl ( 'h2' , { text : 'Set up TickTick' } ) ;
containerEl . createEl ( 'p' , {
text : 'Connect this plugin to your TickTick account in two steps. You only need to do this once.'
} ) ;
new Setting ( containerEl )
. setName ( 'Step 1 — Enter your TickTick app credentials' )
. setHeading ( ) ;
const step1 = containerEl . createEl ( 'p' ) ;
step1 . appendText ( 'Sign in to the ' ) ;
const portalLink = step1 . createEl ( 'a' , {
text : 'TickTick Developer Portal' ,
href : 'https://developer.ticktick.com/'
} ) ;
portalLink . setAttr ( 'target' , '_blank' ) ;
portalLink . setAttr ( 'rel' , 'noopener' ) ;
step1 . appendText ( ', create an app, and copy its Client ID and Client Secret into the fields below. In the portal, set the app\'s Redirect URI to the value shown in the Redirect URI field.' ) ;
2025-03-24 02:38:44 +00:00
new Setting ( containerEl )
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
. setName ( 'Client ID' )
2025-03-24 02:38:44 +00:00
. addText ( text = >
text
. setPlaceholder ( 'Your Client ID' )
. setValue ( this . plugin . settings . clientId || '' )
. onChange ( async ( value ) = > {
this . plugin . settings . clientId = value . trim ( ) ;
await this . plugin . saveSettings ( ) ;
} )
) ;
new Setting ( containerEl )
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
. setName ( 'Client Secret' )
2025-03-24 02:38:44 +00:00
. addText ( text = > {
text . inputEl . type = 'password' ;
text . setPlaceholder ( '••••••••••' )
. setValue ( this . plugin . settings . clientSecret || '' )
. onChange ( async ( value ) = > {
this . plugin . settings . clientSecret = value . trim ( ) ;
await this . plugin . saveSettings ( ) ;
} ) ;
return text ;
} ) ;
2025-03-31 00:45:19 +00:00
new Setting ( containerEl )
. setName ( 'Redirect URI' )
2026-06-05 16:16:26 +00:00
. setDesc ( 'Copy this exact value into your TickTick app\'s Redirect URI field in the developer portal. Do not add a trailing slash — the URIs must match exactly. Only change it here if you self-host the callback page.' )
2025-03-31 00:45:19 +00:00
. addText ( text = >
text
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
. setPlaceholder ( DEFAULT_SETTINGS . redirectUri ! )
2025-03-31 00:45:19 +00:00
. setValue ( this . plugin . settings . redirectUri || '' )
. onChange ( async ( value ) = > {
2026-06-05 16:16:26 +00:00
this . plugin . settings . redirectUri = value . trim ( ) . replace ( /\/+$/ , '' ) ;
2025-03-31 00:45:19 +00:00
await this . plugin . saveSettings ( ) ;
} )
) ;
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
new Setting ( containerEl )
. setName ( 'Step 2 — Authorize' )
. setHeading ( ) ;
containerEl . createEl ( 'p' , {
text : 'Tap Connect, then tap the link in the popup to sign in to TickTick and approve access. The callback page will either return you to Obsidian automatically, or show you an authorization code — if you see a code, copy it and paste it in the field below.'
} ) ;
new Setting ( containerEl )
. setName ( 'Connect to TickTick' )
. addButton ( button = > {
button . setButtonText ( 'Connect' ) . setCta ( ) . onClick ( async ( ) = > {
await this . plugin . startAuthFlow ( ) ;
} ) ;
} ) ;
new Setting ( containerEl )
. setName ( 'Authorization code' )
. setDesc ( 'Only needed if the callback page showed you a code instead of returning you to Obsidian automatically.' )
. addText ( text = >
text
. setPlaceholder ( 'Paste authorization code' )
. onChange ( async ( code ) = > {
if ( code . trim ( ) ) {
await this . plugin . exchangeAuthCodeForToken ( code . trim ( ) ) ;
text . setValue ( '' ) ;
this . display ( ) ;
}
} )
) ;
}
private renderConnectedView ( containerEl : HTMLElement ) : void {
containerEl . createEl ( 'h2' , { text : 'Connected to TickTick' } ) ;
containerEl . createEl ( 'p' , {
text : 'Use the "Create TickTick task" command from any note to send the current line or paragraph to TickTick.'
} ) ;
new Setting ( containerEl )
. setName ( 'Plugin behavior' )
. setHeading ( ) ;
2025-03-24 02:38:44 +00:00
new Setting ( containerEl )
2026-03-11 23:41:17 +00:00
. setName ( 'Selection mode' )
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
. setDesc ( 'Capture only the current line or the entire paragraph.' )
2026-03-11 23:41:17 +00:00
. addDropdown ( dropdown = >
dropdown
. addOption ( 'line' , 'Current line' )
. addOption ( 'paragraph' , 'Entire paragraph' )
. setValue ( this . plugin . settings . selectionMode )
. onChange ( async ( value : string ) = > {
this . plugin . settings . selectionMode = value as 'line' | 'paragraph' ;
await this . plugin . saveSettings ( ) ;
} )
) ;
new Setting ( containerEl )
. setName ( 'Tag position' )
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
. setDesc ( 'Where the #ticktick tag is added relative to the text.' )
2026-03-11 23:41:17 +00:00
. addDropdown ( dropdown = >
dropdown
. addOption ( 'append' , 'Append (end)' )
. addOption ( 'prepend' , 'Prepend (beginning)' )
. setValue ( this . plugin . settings . tagPosition )
. onChange ( async ( value : string ) = > {
this . plugin . settings . tagPosition = value as 'append' | 'prepend' ;
await this . plugin . saveSettings ( ) ;
} )
) ;
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
const details = containerEl . createEl ( 'details' , { cls : 'ticktick-advanced' } ) ;
details . style . marginTop = '2em' ;
const summary = details . createEl ( 'summary' , { text : 'Advanced — Connection details' } ) ;
summary . style . cursor = 'pointer' ;
summary . style . fontWeight = '600' ;
summary . style . padding = '0.5em 0' ;
new Setting ( details )
. setName ( 'Reconnect' )
. setDesc ( 'Re-run the OAuth flow. Use if your token can no longer be refreshed.' )
. addButton ( button = > {
button . setButtonText ( 'Reconnect' ) . onClick ( async ( ) = > {
await this . plugin . startAuthFlow ( ) ;
} ) ;
} ) ;
new Setting ( details )
. setName ( 'Authorization code' )
. setDesc ( 'Manual fallback if reconnecting did not return you to Obsidian automatically.' )
2025-03-24 02:38:44 +00:00
. addText ( text = >
text
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
. setPlaceholder ( 'Paste authorization code' )
. onChange ( async ( code ) = > {
if ( code . trim ( ) ) {
await this . plugin . exchangeAuthCodeForToken ( code . trim ( ) ) ;
text . setValue ( '' ) ;
this . display ( ) ;
}
2025-03-24 02:38:44 +00:00
} )
) ;
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
new Setting ( details )
. setName ( 'Disconnect' )
. setDesc ( 'Clear stored tokens. You will need to authorize again to create tasks.' )
. addButton ( button = > {
button . setButtonText ( 'Disconnect' ) . setWarning ( ) . onClick ( async ( ) = > {
this . plugin . settings . accessToken = '' ;
this . plugin . settings . refreshToken = undefined ;
this . plugin . settings . tokenExpiry = undefined ;
await this . plugin . saveSettings ( ) ;
new Notice ( 'Disconnected from TickTick.' ) ;
this . display ( ) ;
} ) ;
} ) ;
new Setting ( details )
. setName ( 'Client ID' )
2025-03-24 02:38:44 +00:00
. addText ( text = >
text
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
. setValue ( this . plugin . settings . clientId || '' )
2025-03-24 02:38:44 +00:00
. onChange ( async ( value ) = > {
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
this . plugin . settings . clientId = value . trim ( ) ;
2025-03-24 02:38:44 +00:00
await this . plugin . saveSettings ( ) ;
} )
) ;
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
new Setting ( details )
. setName ( 'Client Secret' )
. addText ( text = > {
text . inputEl . type = 'password' ;
text . setPlaceholder ( '••••••••••' )
. setValue ( this . plugin . settings . clientSecret || '' )
. onChange ( async ( value ) = > {
this . plugin . settings . clientSecret = value . trim ( ) ;
await this . plugin . saveSettings ( ) ;
} ) ;
return text ;
2025-03-24 02:38:44 +00:00
} ) ;
2026-05-11 02:11:58 +00:00
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
new Setting ( details )
. setName ( 'Redirect URI' )
2026-06-05 16:16:26 +00:00
. setDesc ( 'Must match the value registered in your TickTick app exactly, with no trailing slash.' )
2026-05-11 02:11:58 +00:00
. addText ( text = >
text
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
. setValue ( this . plugin . settings . redirectUri || '' )
. onChange ( async ( value ) = > {
2026-06-05 16:16:26 +00:00
this . plugin . settings . redirectUri = value . trim ( ) . replace ( /\/+$/ , '' ) ;
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
await this . plugin . saveSettings ( ) ;
2026-05-11 02:11:58 +00:00
} )
) ;
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
new Setting ( details )
. setName ( 'Access token' )
. setDesc ( 'Stored access token (read-only).' )
. addText ( text = > {
text . inputEl . readOnly = true ;
text . setValue ( this . plugin . settings . accessToken || '' ) ;
} ) ;
new Setting ( details )
. setName ( 'Refresh token' )
. setDesc ( 'Stored refresh token (read-only).' )
. addText ( text = > {
text . inputEl . readOnly = true ;
text . setValue ( this . plugin . settings . refreshToken || '' ) ;
} ) ;
2025-03-24 02:38:44 +00:00
}
Split settings into onboarding view and connected view
The previous flat list mixed one-time setup (credentials, OAuth) with
day-to-day options (selection mode, tag position) and persistent debug
fields (access/refresh tokens), making the order confusing.
Now the panel renders one of two views based on whether an access token
is stored:
Setup view (not connected):
- Step 1: Client ID / Client Secret / Redirect URI with a link to
the TickTick Developer Portal and instructions to register the
redirect URI there.
- Step 2: Connect button followed immediately by the manual-paste
authorization code field, with instructions covering both the
automatic redirect and the manual paste paths.
Connected view:
- Header confirms the connection.
- Plugin behavior (selection mode, tag position) is now the primary
content, surfaced immediately.
- Connection details (credentials, tokens, reconnect, disconnect,
manual code paste) are tucked into a collapsed <details> block so
they do not crowd the everyday options.
Also: token fields are now read-only, and a disconnect button clears
stored tokens to re-authorize cleanly.
2026-05-11 02:22:16 +00:00
}