Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
{
"editor.formatOnSave": true,
"autoimport.doubleQuotes": false,
"java.configuration.updateBuildConfiguration": "disabled",
"prettier.requireConfig": true,
"javascript.format.enable": true,
"js/ts.format.enabled": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.tabWidth": 2,
"prettier.useTabs": false,
"javascript.format.semicolons": "insert",
"js/ts.format.semicolons": "insert",
"[scss]": {
"editor.defaultFormatter": "vscode.css-language-features"
},
Expand All @@ -27,6 +25,10 @@
"attr_quotes": "single"
}
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"biome.lsp.bin": "./node_modules/.bin/biome",
"cSpell.words": [
"abap",
"Acode",
Expand Down Expand Up @@ -126,6 +128,7 @@
"flac",
"Flix",
"floobits",
"FOXBIZ",
"Foxdebug",
"freemarker",
"gamemaker",
Expand Down Expand Up @@ -372,8 +375,5 @@
"wxss",
"xquery",
"Zeek"
],
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
}
]
}
20 changes: 8 additions & 12 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,14 @@
},
"files": {
"includes": [
"**/src/**/*",
"**/utils/**/*.js",
"!**/www/build/**/*",
"**/www/res/**/*.css",
"**/src/plugins/terminal/**",
"!**/ace-builds",
"!**/src/plugins/**/*",
"!**/plugins/**/*",
"!**/hooks/**/*",
"!**/fastlane/**/*",
"!**/res/**/*",
"!**/platforms/**/*"
"src/**/*.js",
"utils/**/*.js",
"!src/plugins/**/*.js",
"!www/**/*",
"!plugins/**/*",
"!hooks/**/*",
"!fastlane/**/*",
"!platforms/**/*"
]
}
}
3 changes: 1 addition & 2 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{
"exclude": ["**/node_modules", "**/platforms", "**/www", "www/js/ace/**/*"],
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"*": ["*"]
"*": ["./src/*"]
}
},
"include": ["src/**/*"],
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
"com.foxdebug.acode.rk.exec.terminal": {},
"com.foxdebug.acode.rk.customtabs": {},
"com.foxdebug.acode.rk.plugin.plugincontext": {},
"com.foxdebug.acode.rk.auth": {},
"cordova-plugin-system": {}
"cordova-plugin-system": {},
"com.foxdebug.acode.rk.auth": {}
},
"platforms": [
"android"
Expand Down Expand Up @@ -187,4 +187,4 @@
"@codemirror/view": "^6.40.0"
},
"browserslist": "cover 100%,not android < 5"
}
}
9 changes: 8 additions & 1 deletion src/cm/lsp/serverLauncher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const STATUS_FAILED: InstallStatus = "failed";

const AXS_BINARY = "$PREFIX/axs";

let alreadyInformed = false;

function getTerminalRequiredMessage(): string {
return (
strings?.terminal_required_message_for_lsp ??
Expand Down Expand Up @@ -1081,7 +1083,12 @@ export async function ensureServerRunning(
} catch {}
if (!isTerminalInstalled) {
const message = getTerminalRequiredMessage();
alert(strings?.error, message);

if (!alreadyInformed){
alreadyInformed = true;
alert(strings?.error, message);
}

const unavailable: LspError = new Error(message);
unavailable.code = "LSP_SERVER_UNAVAILABLE";
throw unavailable;
Expand Down
146 changes: 92 additions & 54 deletions src/components/sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@ import toast from "components/toast";
import Ref from "html-tag-js/ref";
import actionStack from "lib/actionStack";
import auth, { loginEvents } from "lib/auth";
import constants from "lib/constants";
import config from "lib/config";

/**
* @typedef {object} SideBar
* @extends HTMLElement
* @property {function():void} hide
* @property {function():void} toggle
* @property {function():void} onshow
*/

/**@type {HTMLElement} */
let $sidebar;
/**@type {Array<(el:HTMLElement)=>boolean>} */
let preventSlideTests = [];
Expand All @@ -14,14 +23,6 @@ const events = {
hide: [],
};

/**
* @typedef {object} SideBar
* @extends HTMLElement
* @property {function():void} hide
* @property {function():void} toggle
* @property {function():void} onshow
*/

/**
* Create a sidebar
* @param {HTMLElement} [$container] - the element that will contain the sidebar
Expand All @@ -31,7 +32,7 @@ const events = {
function create($container, $toggler) {
let { innerWidth } = window;

const START_THRESHOLD = constants.SIDEBAR_SLIDE_START_THRESHOLD_PX; //Point where to start swipe
const START_THRESHOLD = config.SIDEBAR_SLIDE_START_THRESHOLD_PX; //Point where to start swipe
const MIN_WIDTH = 200; //Min width of the side bar
const MAX_WIDTH = () => innerWidth * 0.7; //Max width of the side bar
const resizeBar = Ref();
Expand Down Expand Up @@ -103,36 +104,53 @@ function create($container, $toggler) {

async function handleUserIconClick(e) {
try {
const isLoggedIn = await auth.isLoggedIn();

if (!isLoggedIn) {
auth.openLoginUrl();
const user = await auth.getLoggedInUser();

if (!user) {
CustomTabs.open(
`${config.BASE_URL}/login?redirect=app`,
{ showTitle: true },
() => {},
() => {},
);
} else {
toggleUserMenu();
const menu = userContextMenu.el;
const isActive = menu.classList.toggle("active");

if (isActive) {
const menuName = userContextMenu.el.querySelector(".user-menu-name");
const menuEmail =
userContextMenu.el.querySelector(".user-menu-email");

if (menuName) {
menuName.content = (
<div style={{ display: "flex" }}>
{Boolean(user.verified) && (
<span className="icon verified"></span>
)}
{user.name}
{Boolean(user.acode_pro) && <span className="badge">Pro</span>}
</div>
);
}

if (menuEmail) {
menuEmail.textContent = user.email || "";
}

setTimeout(() => {
document.addEventListener("click", handleClickOutside);
}, 10);
} else {
document.removeEventListener("click", handleClickOutside);
}
}
} catch (error) {
console.error("Error checking login status:", error);
toast("Error checking login status", 3000);
}
}

function toggleUserMenu() {
const menu = userContextMenu.el;
const isActive = menu.classList.toggle("active");

if (isActive) {
// Populate user info
updateUserMenuInfo();

// Add click outside listener
setTimeout(() => {
document.addEventListener("click", handleClickOutside);
}, 10);
} else {
document.removeEventListener("click", handleClickOutside);
}
}

function handleClickOutside(e) {
if (
!userContextMenu.el.contains(e.target) &&
Expand All @@ -144,23 +162,6 @@ function create($container, $toggler) {
}
}

async function updateUserMenuInfo() {
try {
const userInfo = await auth.getUserInfo();
if (userInfo) {
const menuName = userContextMenu.el.querySelector(".user-menu-name");
const menuEmail = userContextMenu.el.querySelector(".user-menu-email");
menuName.textContent = userInfo.name || "Anonymous";
if (userInfo.isAdmin) {
menuName.innerHTML += ' <span class="badge">Admin</span>';
}
menuEmail.textContent = userInfo.email || "";
}
} catch (error) {
console.error("Error fetching user info:", error);
}
}

async function handleLogout() {
try {
const success = await auth.logout();
Expand All @@ -178,8 +179,6 @@ function create($container, $toggler) {
}

async function updateSidebarAvatar() {
const avatarUrl = await auth.getAvatar();
// Remove existing icon or avatar
const existingIcon = userAvatar.el.querySelector(".icon");
const existingAvatar = userAvatar.el.querySelector(".avatar");

Expand All @@ -190,20 +189,59 @@ function create($container, $toggler) {
existingAvatar.remove();
}

if (avatarUrl?.startsWith("data:") || avatarUrl?.startsWith("http")) {
// Create and add avatar image
const user = await auth.getLoggedInUser();

if (user) {
const avatarUrl = user.github
? `https://avatars.githubusercontent.com/${user.github}`
: generateInitialsAvatar(user.name);
const avatarImg = document.createElement("img");
avatarImg.className = "avatar";
avatarImg.src = avatarUrl;
userAvatar.append(avatarImg);
} else {
// Fallback to default icon
const defaultIcon = document.createElement("span");
defaultIcon.className = "icon account_circle";
userAvatar.append(defaultIcon);
}
}

function generateInitialsAvatar(name) {
const nameParts = name.split(" ");
const initials =
nameParts.length >= 2
? `${nameParts[0][0]}${nameParts[1][0]}`.toUpperCase()
: nameParts[0][0].toUpperCase();

const canvas = document.createElement("canvas");
canvas.width = 100;
canvas.height = 100;
const ctx = canvas.getContext("2d");

const colors = [
"#2196F3",
"#9C27B0",
"#E91E63",
"#009688",
"#4CAF50",
"#FF9800",
];
ctx.fillStyle =
colors[
name.split("").reduce((acc, char) => acc + char.charCodeAt(0), 0) %
colors.length
];
ctx.fillRect(0, 0, 100, 100);

ctx.fillStyle = "#ffffff";
ctx.font = "bold 40px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(initials, 50, 50);

return canvas.toDataURL();
}

function onWindowResize() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/dialogs/rateBox.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import constants from "lib/constants";
import config from "lib/config";
import template from "views/rating.hbs";
import box from "./box";

Expand Down Expand Up @@ -34,7 +34,7 @@ function rateBox() {
const stars = getStars(val);
const subject = "feedback - Acode editor";
const textBody = stars + "</br>%0A" + getFeedbackBody("</br>%0A");
const email = constants.FEEDBACK_EMAIL;
const email = config.FEEDBACK_EMAIL;
system.openInBrowser(
`mailto:${email}?subject=${subject}&body=${textBody}`,
);
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/editorFileTab.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import constants from "lib/constants";
import config from "lib/config";
import settings from "lib/settings";

const opts = { passive: false };
Expand Down Expand Up @@ -82,7 +82,7 @@ export default function startDrag(e) {
}

if (settings.value.vibrateOnTap) {
navigator.vibrate(constants.VIBRATION_TIME);
navigator.vibrate(config.VIBRATION_TIME);
}

$tab = e.target;
Expand Down
4 changes: 2 additions & 2 deletions src/handlers/quickToolsInit.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import quickTools from "components/quickTools";
import constants from "lib/constants";
import config from "lib/config";
import appSettings from "lib/settings";
import actions, { key } from "./quickTools";

Expand Down Expand Up @@ -300,7 +300,7 @@ function oncontextmenu(e) {
const { editor, activeFile } = editorManager;

if (isClickMode && appSettings.value.vibrateOnTap) {
navigator.vibrate(constants.VIBRATION_TIME_LONG);
navigator.vibrate(config.VIBRATION_TIME_LONG);
$el.classList.add("active");
}

Expand Down
Loading