···3637**App Development**
3839+Building the Android version requires Java 17. On Ubuntu you can run
40+`sudo apt install openjdk-17-jdk`.
41+42```
43cd js/app
44
···1+// This file serves as a central hub for re-exporting pre-typed Redux hooks.
2+// These imports are restricted elsewhere to ensure consistent
3+// usage of typed hooks throughout the application.
4+// We disable the ESLint rule here because this is the designated place
5+// for importing and re-exporting the typed versions of hooks.
6+/* eslint-disable @typescript-eslint/no-restricted-imports */
7+import { useDispatch, useSelector } from "react-redux";
8+import type { AppDispatch, RootState } from "./store";
9+10+// Use throughout your app instead of plain `useDispatch` and `useSelector`
11+export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
12+export const useAppSelector = useSelector.withTypes<RootState>();
···1+import type { Action, ThunkAction } from "@reduxjs/toolkit";
2+import { combineSlices, configureStore } from "@reduxjs/toolkit";
3+import { setupListeners } from "@reduxjs/toolkit/query";
4+import { aquareumSlice } from "features/aquareum/aquareumSlice";
5+import { blueskySlice } from "features/bluesky/blueskySlice";
6+// import { counterSlice } from "../features/counter/counterSlice"
7+// import { quotesApiSlice } from "../features/quotes/quotesApiSlice"
8+9+// `combineSlices` automatically combines the reducers using
10+// their `reducerPath`s, therefore we no longer need to call `combineReducers`.
11+const rootReducer = combineSlices(blueskySlice, aquareumSlice);
12+// Infer the `RootState` type from the root reducer
13+export type RootState = ReturnType<typeof rootReducer>;
14+15+// The store setup is wrapped in `makeStore` to allow reuse
16+// when setting up tests that need the same store config
17+export const makeStore = (preloadedState?: Partial<RootState>) => {
18+ const store = configureStore({
19+ reducer: rootReducer,
20+ // Adding the api middleware enables caching, invalidation, polling,
21+ // and other useful features of `rtk-query`.
22+ middleware: (getDefaultMiddleware) => {
23+ return getDefaultMiddleware({
24+ serializableCheck: {
25+ // Ignore these action types
26+ ignoredActions: [],
27+ // Ignore these field paths in all actions
28+ ignoredActionPaths: ["payload"],
29+ // Ignore these paths in the state
30+ ignoredPaths: [/^bluesky\..*/],
31+ },
32+ });
33+ },
34+ preloadedState,
35+ });
36+ // configure listeners using the provided defaults
37+ // optional, but required for `refetchOnFocus`/`refetchOnReconnect` behaviors
38+ setupListeners(store.dispatch);
39+ return store;
40+};
41+42+export const store = makeStore();
43+44+// Infer the type of `store`
45+export type AppStore = typeof store;
46+// Infer the `AppDispatch` type from the store itself
47+export type AppDispatch = AppStore["dispatch"];
48+export type AppThunk<ThunkReturnType = void> = ThunkAction<
49+ ThunkReturnType,
50+ RootState,
51+ unknown,
52+ Action
53+>;
···115 fs.StringVar(&cli.PKCS11KeypairLabel, "pkcs11-keypair-label", "", "label of signing keypair on PKCS11 token")
116 fs.StringVar(&cli.PKCS11KeypairID, "pkcs11-keypair-id", "", "id of signing keypair on PKCS11 token")
117 fs.StringVar(&cli.StreamerName, "streamer-name", "", "name of the person streaming from this aquareum node")
0118 cli.AddressSliceFlag(fs, &cli.AllowedStreams, "allowed-streams", "", "comma-separated list of addresses that this node will replicate")
119 cli.StringSliceFlag(fs, &cli.Peers, "peers", "", "other aquareum nodes to replicate to")
120 cli.DebugFlag(fs, &cli.Debug, "debug", "", "modified log verbosity for specific functions or files in form func=ToHLS:3,file=gstreamer.go:4")
···392 if err != nil {
393 return err
394 }
395- err = mod.UpdateSettings(&model.Settings{
396- ID: testMediaSigner.Pub.String(),
397- Streamer: "stream-self-tester",
398- Title: "test-stream",
399 })
400 if err != nil {
401 return err
···115 fs.StringVar(&cli.PKCS11KeypairLabel, "pkcs11-keypair-label", "", "label of signing keypair on PKCS11 token")
116 fs.StringVar(&cli.PKCS11KeypairID, "pkcs11-keypair-id", "", "id of signing keypair on PKCS11 token")
117 fs.StringVar(&cli.StreamerName, "streamer-name", "", "name of the person streaming from this aquareum node")
118+ fs.StringVar(&cli.FrontendProxy, "dev-frontend-proxy", "", "(FOR DEVELOPMENT ONLY) proxy frontend requests to this address instead of using the bundled frontend")
119 cli.AddressSliceFlag(fs, &cli.AllowedStreams, "allowed-streams", "", "comma-separated list of addresses that this node will replicate")
120 cli.StringSliceFlag(fs, &cli.Peers, "peers", "", "other aquareum nodes to replicate to")
121 cli.DebugFlag(fs, &cli.Debug, "debug", "", "modified log verbosity for specific functions or files in form func=ToHLS:3,file=gstreamer.go:4")
···393 if err != nil {
394 return err
395 }
396+ err = mod.UpdateIdentity(&model.Identity{
397+ ID: testMediaSigner.Pub.String(),
398+ Handle: "stream-self-tester",
399+ DID: "",
400 })
401 if err != nil {
402 return err