mirror of
https://github.com/taskgenius/taskgenius-plugin.git
synced 2026-07-22 06:40:25 +00:00
Expand onboarding wizard with new interactive steps to guide users through UI architecture selection: - Add animated typing intro component with AI-style streaming effect - Add UI mode selection step (Fluent vs Legacy interface styles) - Add Fluent placement configuration (Sideleaves vs Inline layout) - Refactor onboarding flow from 5 to 7 steps with conditional branching - Apply selected architecture preferences to plugin settings - Add visual mode classes and enhanced styling support The new flow allows users to customize their Task Genius experience during initial setup while maintaining backward compatibility with existing configurations.
112 lines
2.9 KiB
TypeScript
112 lines
2.9 KiB
TypeScript
import { t } from "@/translations/helper";
|
|
|
|
export class IntroTyping {
|
|
private timers: number[] = [];
|
|
|
|
cleanup() {
|
|
this.timers.forEach((id) => window.clearTimeout(id));
|
|
this.timers = [];
|
|
}
|
|
|
|
render(container: HTMLElement) {
|
|
container.empty();
|
|
const wrap = container.createDiv({cls: "intro-typing"});
|
|
|
|
const line1 = wrap.createEl("h1", {cls: "intro-line intro-line-1"});
|
|
const line2 = wrap.createEl("h2", {cls: "intro-line intro-line-2"});
|
|
const line3 = wrap.createEl("p", {cls: "intro-line intro-line-3"});
|
|
const line4 = wrap.createEl("p", {cls: "intro-line intro-line-4"});
|
|
|
|
const seq = [
|
|
{
|
|
el: line1,
|
|
text: t("Hi,"),
|
|
speed: 35
|
|
},
|
|
{
|
|
el: line2,
|
|
text: t("Thank you for using Task Genius"),
|
|
speed: 25
|
|
},
|
|
{
|
|
el: line3,
|
|
text: t("In the following steps, you will gradually set up Task Genius to get a more suitable environment for you"),
|
|
speed: 20
|
|
},
|
|
{
|
|
el: line4,
|
|
text: t("In the current version, Task Genius provides a brand new visual and interactive experience: Fluent; while also providing the option to return to the previous interface. Which one do you prefer?"),
|
|
speed: 20
|
|
},
|
|
];
|
|
|
|
this.aiStreamSequence(seq);
|
|
}
|
|
|
|
/**
|
|
* AI-style streaming text effect with smooth character fade-in
|
|
*/
|
|
private aiStreamSequence(seq: { el: HTMLElement; text: string; speed: number }[]) {
|
|
const streamLine = (idx: number) => {
|
|
if (idx >= seq.length) return;
|
|
const {el, text, speed} = seq[idx];
|
|
|
|
// Clear and prepare element
|
|
el.empty();
|
|
el.addClass("is-streaming");
|
|
|
|
// Create individual character spans for smooth animation
|
|
const chars: HTMLElement[] = [];
|
|
for (let i = 0; i < text.length; i++) {
|
|
const char = text[i];
|
|
const span = el.createSpan({
|
|
cls: "intro-char",
|
|
text: char,
|
|
});
|
|
// Special handling for spaces to preserve layout
|
|
if (char === " ") {
|
|
span.addClass("intro-char-space");
|
|
}
|
|
chars.push(span);
|
|
}
|
|
|
|
// Create cursor element that will follow the characters
|
|
const cursor = el.createSpan({
|
|
cls: "intro-cursor",
|
|
text: "▊",
|
|
});
|
|
|
|
// Animate characters with AI-style streaming effect
|
|
let charIndex = 0;
|
|
const animateChar = () => {
|
|
if (charIndex < chars.length) {
|
|
const char = chars[charIndex];
|
|
// Add small random variation for more natural feel
|
|
const jitter = Math.random() * speed * 0.3;
|
|
char.addClass("intro-char-visible");
|
|
|
|
// Move cursor after the just-revealed character
|
|
char.after(cursor);
|
|
|
|
charIndex++;
|
|
const id = window.setTimeout(animateChar, speed + jitter);
|
|
this.timers.push(id);
|
|
} else {
|
|
// Line complete, remove cursor and move to next
|
|
cursor.remove();
|
|
el.removeClass("is-streaming");
|
|
el.addClass("stream-complete");
|
|
// Small delay before next line
|
|
const id = window.setTimeout(() => streamLine(idx + 1), 300);
|
|
this.timers.push(id);
|
|
}
|
|
};
|
|
|
|
// Start animation
|
|
animateChar();
|
|
};
|
|
|
|
streamLine(0);
|
|
}
|
|
}
|
|
|