generated from vivid-lapin/ts
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
428 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import React, { useEffect } from "react" | ||
import { useRecoilValue, useSetRecoilState } from "recoil" | ||
import { ContentPlayerPlayingContent, InitPlugin } from "../@types/plugin" | ||
import tailwind from "../tailwind.scss" | ||
import { FileSelector } from "./components/FileSelector" | ||
import { LOCAL_META, Local_RECORDS_WINDOW_ID } from "./constants" | ||
|
||
export const LocalRenderer: InitPlugin["renderer"] = ({ | ||
appInfo, | ||
functions, | ||
atoms, | ||
rpc, | ||
}) => { | ||
return { | ||
...LOCAL_META, | ||
exposedAtoms: [], | ||
sharedAtoms: [], | ||
storedAtoms: [], | ||
setup() { | ||
return | ||
}, | ||
components: [], | ||
destroy() { | ||
return | ||
}, | ||
windows: { | ||
[Local_RECORDS_WINDOW_ID]: () => { | ||
const activeId = useRecoilValue( | ||
atoms.globalActiveContentPlayerIdSelector | ||
) | ||
const setPlayingContent = useSetRecoilState( | ||
atoms.globalContentPlayerPlayingContentFamily(activeId ?? 0) | ||
) | ||
const services = useRecoilValue(atoms.mirakurunServicesSelector) | ||
useEffect(() => { | ||
rpc.setWindowTitle(`ローカル - ${appInfo.name}`) | ||
}, []) | ||
|
||
return ( | ||
<> | ||
<style>{tailwind}</style> | ||
<div className="w-full h-screen bg-gray-100 text-gray-900 flex leading-loose"> | ||
{services ? ( | ||
<FileSelector | ||
services={services} | ||
setPlayingContent={setPlayingContent} | ||
openContentPlayer={( | ||
playingContent: ContentPlayerPlayingContent | ||
) => { | ||
return functions.openContentPlayerWindow({ | ||
playingContent, | ||
}) | ||
}} | ||
requestDialog={rpc.requestDialog} | ||
/> | ||
) : ( | ||
<div className="w-full h-full flex items-center justify-center"> | ||
<div className="text-gray-600 px-4 text-center"> | ||
<p>読み込み中</p> | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
</> | ||
) | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# miraktest-local | ||
|
||
ローカルファイルの再生を行うプラグインです。 | ||
|
||
## ダウンロード | ||
|
||
<https://github.com/ci7lus/miraktest-plugins/releases> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
import { Switch } from "@headlessui/react" | ||
import clsx from "clsx" | ||
import dayjs from "dayjs" | ||
import React, { useState } from "react" | ||
import { File } from "react-feather" | ||
import { | ||
ContentPlayerPlayingContent, | ||
InitPluginInRenderer, | ||
Program, | ||
Service, | ||
} from "../../@types/plugin" | ||
|
||
export const FileSelector: React.VFC<{ | ||
services: Service[] | ||
setPlayingContent: React.Dispatch< | ||
React.SetStateAction<ContentPlayerPlayingContent | null> | ||
> | ||
openContentPlayer: (_: ContentPlayerPlayingContent) => Promise<number> | ||
requestDialog: Parameters<InitPluginInRenderer>[0]["rpc"]["requestDialog"] | ||
}> = ({ services, setPlayingContent, openContentPlayer, requestDialog }) => { | ||
const [filePath, setFilePath] = useState("") | ||
const [startAt, setStartAt] = useState("") | ||
const [duration, setDuration] = useState(30) | ||
const [serviceId, setServiceId] = useState(-1) | ||
|
||
const [isOpenWithNewWindow, setIsOpenWithNewWindow] = useState(false) | ||
|
||
return ( | ||
<div className="w-full h-full flex flex-col"> | ||
<div className="w-full bg-gray-800 text-gray-200"> | ||
<div className="w-full py-2 pl-4 pr-2 flex items-center justify-between"> | ||
<h2 className="font-semibold text-lg">ローカルファイル再生</h2> | ||
</div> | ||
</div> | ||
<div className="w-full flex overflow-auto p-4"> | ||
<form | ||
onSubmit={(e) => { | ||
e.preventDefault() | ||
if (!filePath) { | ||
return | ||
} | ||
const contentType = "Local" | ||
const url = "file://" + filePath | ||
const service = services.find( | ||
(service) => service.serviceId === serviceId | ||
) | ||
const program: Program | undefined = startAt | ||
? { | ||
startAt: dayjs(startAt).unix() * 1000, | ||
duration: duration * 1000 * 60, | ||
id: -1, | ||
networkId: -1, | ||
serviceId, | ||
eventId: -1, | ||
isFree: true, | ||
} | ||
: undefined | ||
const contentPlayload = { | ||
contentType, | ||
url, | ||
program, | ||
service, | ||
} | ||
console.info("再生します:", contentPlayload) | ||
if (isOpenWithNewWindow) { | ||
openContentPlayer(contentPlayload) | ||
} else { | ||
setPlayingContent(contentPlayload) | ||
} | ||
}} | ||
> | ||
<label className="block w-full"> | ||
<span>ファイルを選択</span> | ||
<div className="flex justify-center flex-grow"> | ||
<input | ||
type="text" | ||
className={clsx( | ||
"block mt-1 form-input rounded-l-md w-full text-gray-900 focus:outline-none cursor-pointer" | ||
)} | ||
value={filePath || ""} | ||
onChange={(e) => setFilePath(e.target.value)} | ||
spellCheck={false} | ||
/> | ||
<button | ||
className={clsx( | ||
`px-4 py-2 mt-1 rounded-r-md flex items-center justify-center bg-gray-200 text-gray-900 focus:outline-none cursor-pointer` | ||
)} | ||
onClick={async () => { | ||
const dialog = await requestDialog({ | ||
properties: ["openFile"], | ||
}) | ||
if (dialog.canceled) { | ||
return | ||
} | ||
const path = dialog.filePaths.slice(0).shift() | ||
if (!path) { | ||
return | ||
} | ||
setFilePath(path) | ||
}} | ||
> | ||
<File className="pointer-events-none" size="1.75rem" /> | ||
</button> | ||
</div> | ||
</label> | ||
<div className={clsx("flex", "space-x-2")}> | ||
<label className="block mt-2"> | ||
<span>開始時間</span> | ||
<input | ||
type="datetime-local" | ||
className="block mt-1 form-input rounded-md w-full text-gray-900" | ||
value={startAt || ""} | ||
onChange={(e) => setStartAt(e.target.value)} | ||
/> | ||
</label> | ||
<label className="block mt-2"> | ||
<span>長さ</span> | ||
<input | ||
type="number" | ||
className="block mt-1 form-input rounded-md w-full text-gray-900" | ||
value={duration} | ||
onChange={(e) => { | ||
const p = parseInt(e.target.value) | ||
if (Number.isNaN(p)) { | ||
return | ||
} | ||
setDuration(p) | ||
}} | ||
/> | ||
{startAt ? ( | ||
<span>{dayjs(startAt).add(duration, "minutes").format()}</span> | ||
) : ( | ||
<span>未選択</span> | ||
)} | ||
</label> | ||
</div> | ||
<select | ||
className="appearance-none border rounded py-2 px-2 mt-2 leading-tight focus:outline-none" | ||
value={serviceId} | ||
onChange={(e) => { | ||
const selectedServiceId = parseInt(e.target.value) | ||
if (Number.isNaN(selectedServiceId)) { | ||
setServiceId(-1) | ||
return | ||
} | ||
setServiceId(selectedServiceId) | ||
}} | ||
> | ||
<option value="-1" defaultChecked> | ||
選択解除 | ||
</option> | ||
{services.map((service) => { | ||
return ( | ||
<option key={service.serviceId} value={service.serviceId}> | ||
{service.name} | ||
</option> | ||
) | ||
})} | ||
</select> | ||
<Switch.Group> | ||
<div className="flex items-center mt-4"> | ||
<Switch | ||
checked={isOpenWithNewWindow} | ||
onChange={(e) => setIsOpenWithNewWindow(e)} | ||
className={`${ | ||
isOpenWithNewWindow ? "bg-blue-600" : "bg-gray-300" | ||
} relative inline-flex items-center h-6 rounded-full w-11`} | ||
> | ||
<span | ||
className={`${ | ||
isOpenWithNewWindow ? "translate-x-6" : "translate-x-1" | ||
} inline-block w-4 h-4 transform bg-white rounded-full transition ease-in-out duration-200`} | ||
/> | ||
</Switch> | ||
<Switch.Label className="ml-2"> | ||
新しいウィンドウで開く | ||
</Switch.Label> | ||
</div> | ||
</Switch.Group> | ||
<button | ||
type="submit" | ||
className="bg-blue-500 text-gray-100 p-2 px-3 my-4 rounded-md focus:outline-none cursor-pointer active:bg-gray-200" | ||
> | ||
再生 | ||
</button> | ||
</form> | ||
</div> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export const LOCAL_ID = "io.github.ci7lus.miraktest-plugins.local" | ||
export const LOCAL_PREFIX = "plugins.ci7lus.local" | ||
export const LOCAL_META = { | ||
id: LOCAL_ID, | ||
name: "Local", | ||
author: "ci7lus", | ||
version: "0.0.1", | ||
description: "ローカルファイルの再生を行うプラグインです。", | ||
} | ||
export const Local_RECORDS_WINDOW_ID = `${LOCAL_ID}.records` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { InitPlugin } from "../@types/plugin" | ||
import { LOCAL_META, Local_RECORDS_WINDOW_ID } from "./constants" | ||
|
||
/** | ||
* MirakTest Local | ||
* ローカルファイルの再生を行うプラグイン | ||
*/ | ||
|
||
const main: InitPlugin = { | ||
renderer: | ||
typeof window !== "undefined" | ||
? // eslint-disable-next-line @typescript-eslint/no-var-requires | ||
require("./LocalRenderer").LocalRenderer | ||
: undefined, | ||
main: ({ functions }) => { | ||
return { | ||
...LOCAL_META, | ||
setup: () => { | ||
return | ||
}, | ||
destroy: () => { | ||
return | ||
}, | ||
appMenu: { | ||
label: "ローカルファイル再生", | ||
click: () => { | ||
functions.openWindow({ | ||
name: Local_RECORDS_WINDOW_ID, | ||
isSingletone: true, | ||
args: { | ||
width: 800, | ||
height: 600, | ||
}, | ||
}) | ||
}, | ||
}, | ||
contextMenu: { | ||
label: "ローカルファイル再生", | ||
click: () => { | ||
functions.openWindow({ | ||
name: Local_RECORDS_WINDOW_ID, | ||
isSingletone: true, | ||
args: { | ||
width: 800, | ||
height: 600, | ||
}, | ||
}) | ||
}, | ||
}, | ||
} | ||
}, | ||
} | ||
|
||
export default main |
Oops, something went wrong.