Skip to content

Commit 43cbe3a

Browse files
committed
Release 1.1.2
1 parent 101a86c commit 43cbe3a

7 files changed

Lines changed: 51 additions & 78 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Loopndroll",
3-
"version": "1.1.1",
3+
"version": "1.1.2",
44
"private": true,
55
"type": "module",
66
"packageManager": "pnpm@10.33.0",

src/bun/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
ApplicationMenu,
33
BrowserWindow,
4+
Utils,
45
Updater,
56
defineElectrobunRPC,
67
type UpdateStatusEntry,
@@ -528,8 +529,11 @@ function createWindowRpc() {
528529
createCompletionCheck({ completionCheck }) {
529530
return createCompletionCheck(completionCheck);
530531
},
531-
getTelegramChats({ botToken }) {
532-
return fetchTelegramChats(botToken);
532+
getTelegramChats({ botToken, waitForUpdates }) {
533+
return fetchTelegramChats(botToken, waitForUpdates);
534+
},
535+
openExternalUrl({ url }) {
536+
return Utils.openExternal(url);
533537
},
534538
updateNotification({ notification }) {
535539
return updateLoopNotification(notification);

src/bun/loopndroll.ts

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -3586,79 +3586,6 @@ function getTelegramChatDisplayName(chat: {
35863586
return "Unknown chat";
35873587
}
35883588
3589-
export async function getTelegramChats(botToken: string): Promise<TelegramChatOption[]> {
3590-
const normalizedBotToken = botToken.trim();
3591-
if (normalizedBotToken.length === 0) {
3592-
return [];
3593-
}
3594-
3595-
const response = await fetch(buildTelegramApiUrl(normalizedBotToken, "getUpdates"));
3596-
if (!response.ok) {
3597-
throw new Error(\`Telegram getUpdates failed with status \${response.status}.\`);
3598-
}
3599-
3600-
const payload = (await response.json()) as {
3601-
ok?: boolean;
3602-
result?: Array<{
3603-
message?: {
3604-
chat?: {
3605-
id?: number | string;
3606-
username?: string;
3607-
first_name?: string;
3608-
last_name?: string;
3609-
title?: string;
3610-
};
3611-
from?: {
3612-
username?: string;
3613-
first_name?: string;
3614-
last_name?: string;
3615-
};
3616-
};
3617-
}>;
3618-
description?: string;
3619-
};
3620-
3621-
if (!payload.ok) {
3622-
throw new Error(payload.description || "Telegram getUpdates failed.");
3623-
}
3624-
3625-
const updates = Array.isArray(payload.result) ? payload.result : [];
3626-
const uniqueChats = new Map<string, TelegramChatOption>();
3627-
3628-
for (const update of [...updates].reverse()) {
3629-
const message = update.message;
3630-
const chat = message?.chat;
3631-
if (!chat || (typeof chat.id !== "number" && typeof chat.id !== "string")) {
3632-
continue;
3633-
}
3634-
3635-
const rawUsername = chat.username ?? message?.from?.username ?? null;
3636-
const username =
3637-
typeof rawUsername === "string" && rawUsername.trim().length > 0 ? rawUsername.trim() : null;
3638-
const dedupeKey = username?.toLowerCase() ?? \`chat:\${String(chat.id)}\`;
3639-
if (uniqueChats.has(dedupeKey)) {
3640-
continue;
3641-
}
3642-
3643-
uniqueChats.set(dedupeKey, {
3644-
chatId: String(chat.id),
3645-
username,
3646-
displayName: getTelegramChatDisplayName({
3647-
title: chat.title,
3648-
first_name: chat.first_name ?? message?.from?.first_name,
3649-
last_name: chat.last_name ?? message?.from?.last_name,
3650-
username,
3651-
}),
3652-
});
3653-
3654-
if (uniqueChats.size >= 10) {
3655-
break;
3656-
}
3657-
}
3658-
3659-
return [...uniqueChats.values()];
3660-
}
3661-
36623589
async function main() {
36633590
const input = JSON.parse(await Bun.stdin.text());
36643591
const hookEventName = input.hook_event_name;

src/lib/app-rpc.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ type AppRpc = {
3838
getTelegramChats: (
3939
params: AppRpcSchema["bun"]["requests"]["getTelegramChats"]["params"],
4040
) => Promise<AppRpcSchema["bun"]["requests"]["getTelegramChats"]["response"]>;
41+
openExternalUrl: (
42+
params: AppRpcSchema["bun"]["requests"]["openExternalUrl"]["params"],
43+
) => Promise<AppRpcSchema["bun"]["requests"]["openExternalUrl"]["response"]>;
4144
updateNotification: (
4245
params: AppRpcSchema["bun"]["requests"]["updateNotification"]["params"],
4346
) => Promise<AppRpcSchema["bun"]["requests"]["updateNotification"]["response"]>;

src/lib/loopndroll.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ export async function getTelegramChats(
5555
return (await rpc?.request.getTelegramChats({ botToken, waitForUpdates })) ?? [];
5656
}
5757

58+
export async function openExternalUrl(url: string): Promise<boolean> {
59+
const rpc = await getAppRpc();
60+
return (await rpc?.request.openExternalUrl({ url })) ?? false;
61+
}
62+
5863
export async function updateNotification(notification: UpdateLoopNotificationInput) {
5964
const rpc = await getAppRpc();
6065
return rpc?.request.updateNotification({ notification });

src/pages/settings.tsx

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { ArrowLeft, DotsThree, Plus } from "@phosphor-icons/react";
2-
import { useEffect, useState } from "react";
2+
import { type MouseEvent, useEffect, useState } from "react";
33
import { Controller, useForm } from "react-hook-form";
44
import { useNavigate } from "react-router-dom";
55
import { z } from "zod/v4";
66
import {
77
type CompletionCheck,
88
getTelegramChats,
9+
openExternalUrl,
910
revealHooksFile,
1011
type LoopNotification,
1112
type TelegramChatOption,
@@ -194,6 +195,15 @@ function inferTelegramChatKind(chatId: string): TelegramChatOption["kind"] {
194195
return chatId.trim().startsWith("-") ? "group" : "dm";
195196
}
196197

198+
async function handleExternalLinkClick(event: MouseEvent<HTMLAnchorElement>, url: string) {
199+
event.preventDefault();
200+
201+
const opened = await openExternalUrl(url);
202+
if (!opened) {
203+
window.open(url, "_blank", "noopener,noreferrer");
204+
}
205+
}
206+
197207
function parseCommandsText(commandsText: string) {
198208
return commandsText
199209
.split(/\r?\n/)
@@ -662,7 +672,13 @@ export function SettingsRoute() {
662672
<FieldDescription>
663673
<a
664674
className="text-blue-400 transition-colors hover:text-blue-300"
665-
href="https://t.me/BotFather"
675+
href="https://github.com/lnikell/loopndroll?tab=readme-ov-file#telegram-setup"
676+
onClick={(event) => {
677+
void handleExternalLinkClick(
678+
event,
679+
"https://github.com/lnikell/loopndroll?tab=readme-ov-file#telegram-setup",
680+
);
681+
}}
666682
rel="noreferrer"
667683
target="_blank"
668684
>
@@ -963,6 +979,12 @@ export function SettingsRoute() {
963979
<a
964980
className="text-blue-400 transition-colors hover:text-blue-300"
965981
href="https://github.com/lnikell/loopndroll?tab=readme-ov-file#telegram-commands"
982+
onClick={(event) => {
983+
void handleExternalLinkClick(
984+
event,
985+
"https://github.com/lnikell/loopndroll?tab=readme-ov-file#telegram-commands",
986+
);
987+
}}
966988
rel="noreferrer"
967989
target="_blank"
968990
>
@@ -1061,6 +1083,12 @@ export function SettingsRoute() {
10611083
<a
10621084
className="text-blue-400 transition-colors hover:text-blue-300"
10631085
href="https://github.com/lnikell/loopndroll?tab=readme-ov-file#4-completion-checks"
1086+
onClick={(event) => {
1087+
void handleExternalLinkClick(
1088+
event,
1089+
"https://github.com/lnikell/loopndroll?tab=readme-ov-file#4-completion-checks",
1090+
);
1091+
}}
10641092
rel="noreferrer"
10651093
target="_blank"
10661094
>

src/shared/app-rpc.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,12 @@ export type AppRpcSchema = {
196196
};
197197
response: TelegramChatOption[];
198198
};
199+
openExternalUrl: {
200+
params: {
201+
url: string;
202+
};
203+
response: boolean;
204+
};
199205
updateNotification: {
200206
params: {
201207
notification: UpdateLoopNotificationInput;

0 commit comments

Comments
 (0)