Skip to content

Commit

Permalink
Feat: Initial worship pads
Browse files Browse the repository at this point in the history
  • Loading branch information
Vija02 committed Nov 25, 2024
1 parent 6cc5387 commit 3d39511
Show file tree
Hide file tree
Showing 20 changed files with 653 additions and 213 deletions.
8 changes: 8 additions & 0 deletions plugins/worship-pads/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
root: true,
extends: ["@repo/eslint-config/vite.js"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: true,
},
};
1 change: 1 addition & 0 deletions plugins/worship-pads/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"@repo/prettier-config/index.js"
47 changes: 47 additions & 0 deletions plugins/worship-pads/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@repo/plugin-worship-pads",
"private": true,
"version": "0.0.0",
"main": "./dist/index.js",
"exports": {
".": {
"default": "./dist/index.mjs"
}
},
"scripts": {
"build": "pkgroll && vite build",
"dev": "concurrently \"pkgroll --watch\" \"vite build --watch\""
},
"dependencies": {
"@chakra-ui/react": "^2.10.3",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@r2wc/react-to-web-component": "^2.0.3",
"@repo/base-plugin": "*",
"@repo/ui": "*",
"@tanstack/react-query": "^5.59.16",
"@trpc/client": "^11.0.0-rc.593",
"@trpc/react-query": "^11.0.0-rc.593",
"@trpc/server": "^11.0.0-rc.593",
"@types/react": "npm:types-react@rc",
"@types/react-dom": "npm:types-react-dom@rc",
"framer-motion": "^11.11.10",
"howler": "^2.2.4",
"react": "rc",
"react-dom": "rc",
"react-icons": "^5.3.0",
"valtio": "^2.1.1",
"valtio-yjs": "^0.6.0",
"yjs": "^13.6.20"
},
"devDependencies": {
"@repo/eslint-config": "*",
"@repo/prettier-config": "*",
"@repo/typescript-config": "*",
"@types/howler": "^2",
"@vitejs/plugin-react-swc": "^3.7.1",
"eslint": "^8.57.1",
"pkgroll": "^2.5.1",
"vite": "5.4.10"
}
}
3 changes: 3 additions & 0 deletions plugins/worship-pads/src/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const pluginName = "worship-pads";
export const remoteWebComponentTag = "worship-pads-remote";
export const rendererWebComponentTag = "worship-pads-renderer";
125 changes: 125 additions & 0 deletions plugins/worship-pads/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import {
ObjectToTypedMap,
Plugin,
ServerPluginApi,
TRPCObject,
} from "@repo/base-plugin/server";
import { proxy } from "valtio";
import { bind } from "valtio-yjs";

import {
pluginName,
remoteWebComponentTag,
rendererWebComponentTag,
} from "./consts";
import { PluginBaseData } from "./types";

export const init = (serverPluginApi: ServerPluginApi) => {
serverPluginApi.registerTrpcAppRouter(getAppRouter);
serverPluginApi.onPluginDataCreated(pluginName, onPluginDataCreated);
serverPluginApi.onPluginDataLoaded(pluginName, onPluginDataLoaded);
serverPluginApi.registerSceneCreator(pluginName, {
title: "Worship Pads",
description: "Play an ambient pad to back your worship session",
categories: ["Audio"],
});

serverPluginApi.serveStatic(pluginName, "out");

serverPluginApi.loadJsOnRemoteView(pluginName, `${pluginName}-remote.es.js`);
serverPluginApi.registerRemoteViewWebComponent(
pluginName,
remoteWebComponentTag,
);
serverPluginApi.loadJsOnRendererView(
pluginName,
`${pluginName}-renderer.es.js`,
);
serverPluginApi.registerRendererViewWebComponent(
pluginName,
rendererWebComponentTag,
);
};

const onPluginDataCreated = (
pluginInfo: ObjectToTypedMap<Plugin<PluginBaseData>>,
) => {
const data = proxy(pluginInfo.toJSON() as Plugin<PluginBaseData>);
const unbind = bind(data, pluginInfo as any);

data.pluginData.files = [
{
key: "C",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/C_Major.mp3",
},
{
key: "Db",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/Db_Major.mp3",
},
{
key: "D",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/D_Major.mp3",
},
{
key: "Eb",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/Eb_Major.mp3",
},
{
key: "E",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/E_Major.mp3",
},
{
key: "F",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/F_Major.mp3",
},
{
key: "Gb",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/Gb_Major.mp3",
},
{
key: "G",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/G_Major.mp3",
},
{
key: "Ab",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/Ab_Major.mp3",
},
{
key: "A",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/A_Major.mp3",
},
{
key: "Bb",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/Bb_Major.mp3",
},
{
key: "B",
url: "https://raw.githubusercontent.com/Vija02/theopenpresenter-static/refs/heads/main/worship-pads/karl-verkade-bridge/B_Major.mp3",
},
];

unbind();

return {};
};

const onPluginDataLoaded = (
pluginInfo: ObjectToTypedMap<Plugin<PluginBaseData>>,
) => {
const data = proxy(pluginInfo.toJSON() as Plugin<PluginBaseData>);
const unbind = bind(data, pluginInfo as any);

return {
dispose: () => {
unbind();
},
};
};

const getAppRouter = (t: TRPCObject) => {
return t.router({});
};

export type AppRouter = ReturnType<typeof getAppRouter>;

export * from "./types";
12 changes: 12 additions & 0 deletions plugins/worship-pads/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type PluginBaseData = {
files: {
key: string;
url: string;
}[];
};

export type PluginRendererData = {
currentKey: string;
isPlaying: boolean;
volume: number;
};
17 changes: 17 additions & 0 deletions plugins/worship-pads/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"extends": "@repo/typescript-config/base.json",
"compilerOptions": {
"noEmit": false,
"rootDir": ".",
"outDir": "dist",
"tsBuildInfoFile": "dist/tsconfig.tsbuildinfo",
"declarationDir": "dist",
"lib": ["es2018", "esnext.asynciterable"],
"target": "es2018",
"module": "Preserve",
"esModuleInterop": true,
"moduleResolution": "Node"
},
"include": ["src", "vite.config.ts"],
"references": [{ "path": "../../packages/base-plugin" }]
}
116 changes: 116 additions & 0 deletions plugins/worship-pads/view/Remote/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import {
Box,
Button,
Grid,
Heading,
Slider,
SliderFilledTrack,
SliderMark,
SliderThumb,
SliderTrack,
Stack,
Text,
useBreakpointValue,
} from "@chakra-ui/react";
import { FaStop } from "react-icons/fa";

import { usePluginAPI } from "../pluginApi";

const WorshipPadsRemote = () => {
const pluginApi = usePluginAPI();

const files = pluginApi.scene.useData((x) => x.pluginData.files);
const isPlaying = pluginApi.renderer.useData((x) => x.isPlaying);
const volume = pluginApi.renderer.useData((x) => x.volume);
const currentKey = pluginApi.renderer.useData((x) => x.currentKey);

const mutableRendererData = pluginApi.renderer.useValtioData();

const orientation = useBreakpointValue({
base: "vertical",
md: "horizontal",
}) as "vertical" | "horizontal";

return (
<Stack dir="column" p={3}>
<Heading>Worship Pads</Heading>

<Box>
<Grid
maxW="1200px"
gap="1px"
border="1px solid black"
bg="black"
gridTemplateColumns={{
base: "repeat(3, 1fr)",
md: "repeat(4, 1fr)",
lg: "repeat(6, 1fr)",
}}
>
{files.map((file) => (
<Button
width="100%"
height="100%"
rounded="none"
aspectRatio={1}
bg={isPlaying && currentKey === file.key ? "blue.200" : "white"}
_hover={{ bg: "blue.100" }}
onClick={() => {
mutableRendererData.currentKey = file.key;
mutableRendererData.isPlaying = true;
}}
>
{file.key}
</Button>
))}
</Grid>
</Box>

{isPlaying && (
<Button
onClick={() => {
mutableRendererData.isPlaying = false;
}}
colorScheme="orange"
>
<FaStop />
<Text ml={2}>Stop</Text>
</Button>
)}

<Box>
<Slider
key={orientation}
id="slider"
value={volume ?? 1}
min={0}
max={1}
step={0.01}
orientation={orientation}
colorScheme="teal"
onChange={(v) => {
mutableRendererData.volume = v;
}}
height={{ base: "70vh", md: "100%" }}
width={{ base: "80px", md: "100%" }}
>
<SliderMark value={0.25} mt="1" ml="-2.5" fontSize="sm">
25%
</SliderMark>
<SliderMark value={0.5} mt="1" ml="-2.5" fontSize="sm">
50%
</SliderMark>
<SliderMark value={0.75} mt="1" ml="-2.5" fontSize="sm">
75%
</SliderMark>
<SliderTrack>
<SliderFilledTrack />
</SliderTrack>
<SliderThumb />
</Slider>
</Box>
</Stack>
);
};

export default WorshipPadsRemote;
Loading

0 comments on commit 3d39511

Please sign in to comment.