Skip to content

Commit e1bae74

Browse files
committed
feat(welcome): add welcome tab for first-time users
- Create welcome page component - Show welcome tab automatically on first app launch - Add "welcome" command to command palette
1 parent 715d50d commit e1bae74

File tree

6 files changed

+423
-1
lines changed

6 files changed

+423
-1
lines changed

src/ace/commands.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,14 @@ const commands = [
349349
},
350350
readOnly: true,
351351
},
352+
{
353+
name: "acode:showWelcome",
354+
description: "Show Welcome",
355+
exec() {
356+
acode.exec("welcome");
357+
},
358+
readOnly: true,
359+
},
352360
];
353361

354362
export function setCommands(editor) {

src/lib/commands.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import prompt from "dialogs/prompt";
77
import select from "dialogs/select";
88
import actions from "handlers/quickTools";
99
import recents from "lib/recents";
10+
import About from "pages/about";
1011
import FileBrowser from "pages/fileBrowser";
1112
import plugins from "pages/plugins";
1213
import Problems from "pages/problems/problems";
14+
import openWelcomeTab from "pages/welcome/welcome";
1315
import changeEncoding from "palettes/changeEncoding";
1416
import changeMode from "palettes/changeMode";
1517
import changeTheme from "palettes/changeTheme";
@@ -188,6 +190,10 @@ export default {
188190
FileBrowser();
189191
break;
190192

193+
case "about":
194+
About();
195+
break;
196+
191197
default:
192198
return;
193199
}
@@ -474,4 +480,7 @@ Additional Info:
474480
window.toast("Failed to create terminal");
475481
}
476482
},
483+
welcome() {
484+
openWelcomeTab();
485+
},
477486
};

src/main.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import settings from "lib/settings";
4545
import startAd from "lib/startAd";
4646
import mustache from "mustache";
4747
import plugins from "pages/plugins";
48+
import openWelcomeTab from "pages/welcome";
4849
import otherSettings from "settings/appSettings";
4950
import themes from "theme/list";
5051
import { getEncoding, initEncodings } from "utils/encodings";
@@ -474,7 +475,13 @@ async function loadApp() {
474475

475476
window.log("info", "Started app and its services...");
476477

477-
new EditorFile();
478+
// Show welcome tab on first launch, otherwise create default file
479+
const isFirstLaunch = Number.isNaN(previousVersionCode);
480+
if (isFirstLaunch) {
481+
openWelcomeTab();
482+
} else {
483+
new EditorFile();
484+
}
478485

479486
// load theme plugins
480487
try {

src/pages/welcome/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "./welcome";

src/pages/welcome/welcome.js

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import "./welcome.scss";
2+
import Logo from "components/logo";
3+
import actionStack from "lib/actionStack";
4+
import constants from "lib/constants";
5+
import EditorFile from "lib/editorFile";
6+
7+
/**
8+
* Opens the Welcome tab as an EditorFile page
9+
*/
10+
export default function openWelcomeTab() {
11+
// Check if welcome tab is already open
12+
const existingFile = editorManager.files.find((f) => f.id === "welcome-tab");
13+
if (existingFile) {
14+
existingFile.makeActive();
15+
return;
16+
}
17+
18+
const welcomeContent = createWelcomeContent();
19+
20+
const welcomeFile = new EditorFile("Welcome", {
21+
id: "welcome-tab",
22+
render: true,
23+
type: "page",
24+
content: welcomeContent,
25+
tabIcon: "icon acode",
26+
hideQuickTools: true,
27+
});
28+
29+
// Set custom subtitle for the header
30+
welcomeFile.setCustomTitle(() => "Get Started");
31+
32+
actionStack.push({
33+
id: "welcome-tab",
34+
action: () => welcomeFile.remove(),
35+
});
36+
}
37+
38+
/**
39+
* Creates the welcome tab content
40+
* @returns {HTMLElement}
41+
*/
42+
function createWelcomeContent() {
43+
return (
44+
<div id="welcome-tab" className="welcome-page scroll">
45+
{/* Hero Section */}
46+
<header className="welcome-header">
47+
<Logo />
48+
<div className="welcome-header-text">
49+
<h1>Welcome to Acode</h1>
50+
<p className="tagline">Powerful code editor for Android</p>
51+
</div>
52+
</header>
53+
54+
{/* Get Started Section */}
55+
<section className="welcome-section">
56+
<h2 className="section-label">GET STARTED</h2>
57+
<div className="action-list">
58+
<ActionRow
59+
icon="add"
60+
label={strings["new file"]}
61+
shortcut="Ctrl+N"
62+
onClick={() => acode.exec("new-file")}
63+
/>
64+
<ActionRow
65+
icon="folder_open"
66+
label={strings["open folder"]}
67+
shortcut="Ctrl+O"
68+
onClick={() => acode.exec("open-folder")}
69+
/>
70+
<ActionRow
71+
icon="historyrestore"
72+
label={strings.recent}
73+
onClick={() => acode.exec("recent")}
74+
/>
75+
<ActionRow
76+
icon="tune"
77+
label={strings["command palette"]}
78+
shortcut="Ctrl+Shift+P"
79+
onClick={() => acode.exec("command-palette")}
80+
/>
81+
</div>
82+
</section>
83+
84+
{/* Configure Section */}
85+
<section className="welcome-section">
86+
<h2 className="section-label">CONFIGURE</h2>
87+
<div className="action-list">
88+
<ActionRow
89+
icon="settings"
90+
label={strings.settings}
91+
onClick={() => acode.exec("open", "settings")}
92+
/>
93+
<ActionRow
94+
icon="color_lenspalette"
95+
label={strings["change theme"]}
96+
onClick={() => acode.exec("change-app-theme")}
97+
/>
98+
<ActionRow
99+
icon="extension"
100+
label={strings.explore + " " + strings.plugins}
101+
onClick={() => acode.exec("open", "plugins")}
102+
/>
103+
</div>
104+
</section>
105+
106+
{/* Learn Section */}
107+
<section className="welcome-section">
108+
<h2 className="section-label">LEARN</h2>
109+
<div className="action-list">
110+
<ActionRow
111+
icon="help"
112+
label={strings.help}
113+
onClick={() => acode.exec("open", "help")}
114+
/>
115+
<ActionRow
116+
icon="info_outline"
117+
label={strings.about}
118+
onClick={() => acode.exec("open", "about")}
119+
/>
120+
</div>
121+
</section>
122+
123+
{/* Links Section */}
124+
<section className="welcome-section welcome-links">
125+
<h2 className="section-label">CONNECT</h2>
126+
<div className="link-row">
127+
<LinkItem icon="acode" label="Website" url={constants.WEBSITE_URL} />
128+
<LinkItem icon="github" label="GitHub" url={constants.GITHUB_URL} />
129+
<LinkItem
130+
icon="telegram"
131+
label="Telegram"
132+
url={constants.TELEGRAM_URL}
133+
/>
134+
<LinkItem
135+
icon="discord"
136+
label="Discord"
137+
url={constants.DISCORD_URL}
138+
/>
139+
</div>
140+
</section>
141+
</div>
142+
);
143+
}
144+
145+
/**
146+
* Action row component
147+
*/
148+
function ActionRow({ icon, label, shortcut, onClick }) {
149+
return (
150+
<div className="action-row" onclick={onClick}>
151+
<span className={`icon ${icon}`}></span>
152+
<span className="action-label">{label}</span>
153+
{shortcut && <span className="action-shortcut">{shortcut}</span>}
154+
</div>
155+
);
156+
}
157+
158+
/**
159+
* Link item component - opens URL in external browser
160+
*/
161+
function LinkItem({ icon, label, url }) {
162+
const handleClick = (e) => {
163+
e.preventDefault();
164+
system.openInBrowser(url);
165+
};
166+
167+
return (
168+
<a href={url} className="link-item" onclick={handleClick}>
169+
<span className={`icon ${icon}`}></span>
170+
<span>{label}</span>
171+
</a>
172+
);
173+
}

0 commit comments

Comments
 (0)