Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4dd0775640 | |||
| 4f81431ccd | |||
| 6371787b47 | |||
| f9b2786809 | |||
| a88f7bac09 | |||
| 37e147e3be |
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { NavigationContainer, DarkTheme, DefaultTheme } from "@react-navigation/native";
|
||||
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
|
||||
import { Animated, Platform, ActivityIndicator, View, StyleSheet, StatusBar } from "react-native";
|
||||
import { Animated, Platform, ActivityIndicator, View, StyleSheet, StatusBar, useWindowDimensions } from "react-native";
|
||||
import { useNavigationState } from "@react-navigation/native";
|
||||
import { useFonts } from "expo-font";
|
||||
import { LinearGradient } from "expo-linear-gradient";
|
||||
@@ -38,6 +38,8 @@ const Tab = createBottomTabNavigator<RootTabParamList>();
|
||||
export function AppContainer() {
|
||||
const { areaInfo, areaIconBadgeText, isInfo } = useAreaInfo();
|
||||
const { selectedLine } = useTrainMenu();
|
||||
const { width, height } = useWindowDimensions();
|
||||
const operationScreenKey = width > height ? "operation-landscape" : "operation-portrait";
|
||||
const [isExtraWindowOpen, setIsExtraWindowOpen] = React.useState(false);
|
||||
|
||||
// フェードアニメーション用 (0=通常, 1=追加ウィンドウ青)
|
||||
@@ -185,8 +187,9 @@ export function AppContainer() {
|
||||
areaInfo ? areaIconBadgeText : undefined,
|
||||
isInfo
|
||||
)}
|
||||
children={TNDView}
|
||||
/>
|
||||
>
|
||||
{() => <TNDView key={operationScreenKey} />}
|
||||
</Tab.Screen>
|
||||
</Tab.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
@@ -13,6 +13,7 @@ import { getTime, trainTimeFiltering } from "@/lib/trainTimeFiltering";
|
||||
import { eachTrainDiagramType, StationProps } from "@/lib/CommonTypes";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import { useThemeColors } from "@/lib/theme";
|
||||
import { stackAwareNavigate } from "@/lib/rootNavigation";
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -49,7 +50,7 @@ type props = {
|
||||
export const LED_vision: FC<props> = (props) => {
|
||||
const { station } = props;
|
||||
|
||||
const { navigate, addListener, isFocused } = useNavigation();
|
||||
const { navigate } = useNavigation();
|
||||
const { currentTrain } = useCurrentTrain();
|
||||
const [stationDiagram, setStationDiagram] = useState<{
|
||||
[key: string]: string;
|
||||
@@ -163,7 +164,7 @@ export const LED_vision: FC<props> = (props) => {
|
||||
<AreaDescription
|
||||
numberOfLines={1}
|
||||
areaInfo={areaInfo}
|
||||
onClick={() => alert(areaInfo)}
|
||||
onClick={() => stackAwareNavigate("information")}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1760
-126
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,101 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const repoRoot = path.resolve(__dirname, "..");
|
||||
const sourcePath = path.join(repoRoot, "ndView.tsx");
|
||||
const outputDir = path.join(repoRoot, "docs", "generated");
|
||||
const outputPath = path.join(outputDir, "jrshikoku-operation-info.user.js");
|
||||
|
||||
const source = fs.readFileSync(sourcePath, "utf8");
|
||||
const match = source.match(/return String\.raw`([\s\S]*?)`;\n};/);
|
||||
if (!match) {
|
||||
throw new Error("Failed to locate buildOperationPageScript body in ndView.tsx");
|
||||
}
|
||||
|
||||
let scriptBody = match[1];
|
||||
|
||||
scriptBody = scriptBody.replace(
|
||||
" window.__jrsNativeOperationLayout = ${nativeLayout};",
|
||||
[
|
||||
" window.__jrsNativeOperationLayout = Object.assign({",
|
||||
" forceSignage: true,",
|
||||
" safeAreaLeft: 0,",
|
||||
" safeAreaRight: 0,",
|
||||
" lineBadges: []",
|
||||
" }, window.__TM_OPERATION_INFO_LAYOUT || {});"
|
||||
].join("\n")
|
||||
);
|
||||
|
||||
const nativePostMessageBlock = [
|
||||
" function postMessage(payload) {",
|
||||
" if (!window.ReactNativeWebView) return;",
|
||||
" payload.type = 'operationInfoCapture';",
|
||||
" window.ReactNativeWebView.postMessage(JSON.stringify(payload));",
|
||||
" }"
|
||||
].join("\n");
|
||||
|
||||
const tampermonkeyPostMessageBlock = [
|
||||
" function downloadCapture(dataUrl, fileName) {",
|
||||
" if (!dataUrl) return;",
|
||||
" if (typeof GM_download === 'function') {",
|
||||
" try {",
|
||||
" GM_download({ url: dataUrl, name: fileName, saveAs: true });",
|
||||
" return;",
|
||||
" } catch (error) {",
|
||||
" console.warn('[JRShikoku TM] GM_download failed, falling back to anchor download.', error);",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" var link = document.createElement('a');",
|
||||
" link.href = dataUrl;",
|
||||
" link.download = fileName || ('operation-info-' + Date.now() + '.png');",
|
||||
" link.rel = 'noopener';",
|
||||
" document.body.appendChild(link);",
|
||||
" link.click();",
|
||||
" link.remove();",
|
||||
" }",
|
||||
"",
|
||||
" function postMessage(payload) {",
|
||||
" if (!payload) return;",
|
||||
" if (payload.error) {",
|
||||
" console.error('[JRShikoku TM] capture failed', payload);",
|
||||
" window.alert('運行情報の画像生成に失敗しました。');",
|
||||
" return;",
|
||||
" }",
|
||||
" downloadCapture(payload.dataUrl, payload.fileName);",
|
||||
" }"
|
||||
].join("\n");
|
||||
|
||||
if (!scriptBody.includes(nativePostMessageBlock)) {
|
||||
throw new Error("Failed to locate React Native postMessage block in ndView.tsx");
|
||||
}
|
||||
scriptBody = scriptBody.replace(nativePostMessageBlock, tampermonkeyPostMessageBlock);
|
||||
|
||||
const header = [
|
||||
"// ==UserScript==",
|
||||
"// @name JR四国 運行情報 Inject",
|
||||
"// @namespace https://github.com/harukin/jrshikoku",
|
||||
"// @version 0.1.0",
|
||||
"// @description Run the JR Shikoku operation-info injection on desktop browsers via Tampermonkey.",
|
||||
"// @match https://www.jr-shikoku.co.jp/info/*",
|
||||
"// @run-at document-idle",
|
||||
"// @grant GM_download",
|
||||
"// ==/UserScript==",
|
||||
"",
|
||||
"/* Generated from ndView.tsx by scripts/generate-operation-info-userscript.mjs. */",
|
||||
"",
|
||||
"window.__TM_OPERATION_INFO_LAYOUT = Object.assign({",
|
||||
" forceSignage: true,",
|
||||
" safeAreaLeft: 0,",
|
||||
" safeAreaRight: 0,",
|
||||
" lineBadges: []",
|
||||
"}, window.__TM_OPERATION_INFO_LAYOUT || {});",
|
||||
""
|
||||
].join("\n");
|
||||
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
fs.writeFileSync(outputPath, header + scriptBody.trimStart() + "\n", "utf8");
|
||||
console.log(path.relative(repoRoot, outputPath));
|
||||
Reference in New Issue
Block a user