Files
jrshikoku/components/AndroidWidget/ShortcutWidget.tsx
2026-03-25 01:44:29 +09:00

223 lines
6.1 KiB
TypeScript

import React from "react";
import { FlexWidget, TextWidget } from "react-native-android-widget";
import { getDelayData } from "./TraInfoEXWidget";
import { getInfoString } from "./InfoWidget";
import { getFelicaQuickAccessData } from "./FelicaQuickAccessWidget";
export async function getShortcutData() {
const [delayResult, infoResult, felicaResult] = await Promise.allSettled([
getDelayData(),
getInfoString(),
getFelicaQuickAccessData(),
]);
const delayCount =
delayResult.status === "fulfilled" && delayResult.value.delayString
? delayResult.value.delayString.length
: 0;
const hasInfo =
infoResult.status === "fulfilled" &&
infoResult.value.text != null &&
infoResult.value.text.length > 0;
const amountText =
felicaResult.status === "fulfilled"
? felicaResult.value.amountText
: "未読取";
return { delayCount, hasInfo, amountText };
}
export type ShortcutWidgetProps = {
delayCount: number;
hasInfo: boolean;
amountText: string;
};
const TILE_BG = "#E8F4FB";
const SPACING = 6;
/** 汎用グリッドタイル */
function GridTile({
icon,
label,
sub,
subColor,
badgeText,
badgeColor,
bottomTrailing,
uri,
}: {
icon: string;
label: string;
sub?: string;
subColor?: string;
badgeText?: string;
badgeColor?: string;
bottomTrailing?: string;
uri: string;
}) {
return (
<FlexWidget
style={{
flex: 1,
backgroundColor: TILE_BG,
borderRadius: 10,
padding: 8,
justifyContent: "center",
}}
clickAction="OPEN_URI"
clickActionData={{ uri }}
>
<FlexWidget style={{ flexDirection: "row", alignItems: "center" }}>
<TextWidget text={icon} style={{ fontSize: 22 }} />
<FlexWidget style={{ marginLeft: 6, flex: 1 }}>
{badgeText !== undefined && badgeColor !== undefined ? (
<FlexWidget style={{ flexDirection: "row", alignItems: "center" }}>
<TextWidget
text={label}
style={{ color: "#000000", fontSize: 12, fontWeight: "bold" }}
/>
<FlexWidget
style={{
backgroundColor: badgeColor as any,
borderRadius: 6,
paddingLeft: 4,
paddingRight: 4,
paddingTop: 1,
paddingBottom: 1,
marginLeft: 3,
}}
>
<TextWidget
text={badgeText}
style={{ color: "#ffffff", fontSize: 9, fontWeight: "bold" }}
/>
</FlexWidget>
</FlexWidget>
) : (
<TextWidget
text={label}
style={{ color: "#000000", fontSize: 12, fontWeight: "bold" }}
/>
)}
{sub !== undefined ? (
<TextWidget
text={sub}
style={{ color: (subColor ?? "#555555") as any, fontSize: 10, marginTop: 1 }}
/>
) : (
<TextWidget text="" style={{ fontSize: 1 }} />
)}
</FlexWidget>
</FlexWidget>
{bottomTrailing !== undefined && (
<FlexWidget
style={{
flexDirection: "row",
justifyContent: "flex-end",
width: "match_parent",
}}
>
<TextWidget
text={bottomTrailing}
style={{ color: "#555555", fontSize: 8, fontWeight: "600" }}
/>
</FlexWidget>
)}
</FlexWidget>
);
}
export function ShortcutWidget({ delayCount, hasInfo, amountText }: ShortcutWidgetProps) {
return (
<FlexWidget
style={{
height: "match_parent",
width: "match_parent",
backgroundColor: "#ffffff",
borderRadius: 16,
padding: 8,
}}
>
{/* Row 1: 走行位置 | 遅延速報EX */}
<FlexWidget
style={{
flexDirection: "row",
width: "match_parent",
flex: 1,
}}
>
<GridTile icon="🚃" label="走行位置" sub="列車の現在位置" uri="jrshikoku://positions/apps" />
<FlexWidget style={{ width: SPACING, height: "match_parent" }}>
<TextWidget text="" style={{ fontSize: 1 }} />
</FlexWidget>
<GridTile
icon="⚡"
label="遅延速報EX"
sub="列車の遅延情報"
uri="jrshikoku://open/traininfo"
badgeText={delayCount > 0 ? `${delayCount}` : "なし"}
badgeColor={delayCount > 0 ? "#E53935" : "#9E9E9E"}
/>
</FlexWidget>
{/* Spacer between rows */}
<FlexWidget style={{ height: SPACING, width: "match_parent" }}>
<TextWidget text="" style={{ fontSize: 1 }} />
</FlexWidget>
{/* Row 2: 運行情報 | ICカード */}
<FlexWidget
style={{
flexDirection: "row",
width: "match_parent",
flex: 1,
}}
>
<GridTile
icon="📋"
label="運行情報"
sub="列車の運行状況"
uri="jrshikoku://open/operation"
badgeText={hasInfo ? "あり" : "なし"}
badgeColor={hasInfo ? "#FF7043" : "#9E9E9E"}
/>
<FlexWidget style={{ width: SPACING, height: "match_parent" }}>
<TextWidget text="" style={{ fontSize: 1 }} />
</FlexWidget>
<GridTile
icon="💳"
label="ICカード"
sub={amountText}
subColor="#0099CC"
uri="jrshikoku://open/felica"
/>
</FlexWidget>
{/* Spacer between rows */}
<FlexWidget style={{ height: SPACING, width: "match_parent" }}>
<TextWidget text="" style={{ fontSize: 1 }} />
</FlexWidget>
{/* Row 3: トップメニュー(全幅) */}
<FlexWidget
style={{
flexDirection: "row",
width: "match_parent",
flex: 1,
}}
>
<GridTile
icon="🏠"
label="トップメニュー"
sub="アプリのトップへ"
bottomTrailing="クイックアクセス"
uri="jrshikoku://open/topmenu"
/>
</FlexWidget>
</FlexWidget>
);
}