Skip to content

Commit

Permalink
feat: delta volume change
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsNotGoodName committed Mar 16, 2023
1 parent 15d88aa commit 8e55f43
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 43 deletions.
11 changes: 7 additions & 4 deletions docs/swagger/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions docs/swagger/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -396,11 +396,11 @@
}
}
},
"patch": {
"post": {
"tags": [
"states"
],
"summary": "Patch state",
"summary": "Update state",
"parameters": [
{
"type": "string",
Expand All @@ -415,7 +415,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/http.PatchState"
"$ref": "#/definitions/http.PostState"
}
}
],
Expand Down Expand Up @@ -451,7 +451,7 @@
}
}
},
"http.PatchState": {
"http.PostState": {
"type": "object",
"properties": {
"audio_source": {
Expand All @@ -465,6 +465,9 @@
},
"volume": {
"type": "integer"
},
"volume_delta": {
"type": "integer"
}
}
},
Expand Down
25 changes: 16 additions & 9 deletions http/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,23 +246,24 @@ func (a API) GetState(c echo.Context) error {
return c.JSON(http.StatusOK, state)
}

type PatchState struct {
type PostState struct {
Power *bool `json:"power,omitempty" validate:"optional"`
AudioSource *string `json:"audio_source,omitempty" validate:"optional"`
Preset *int `json:"preset,omitempty" validate:"optional"`
Volume *int `json:"volume,omitempty" validate:"optional"`
VolumeDelta *int `json:"volume_delta,omitempty" validate:"optional"`
}

// @Summary Patch state
// @Summary Update state
// @Tags states
// @Param uuid path string true "Radio UUID"
// @Param state body PatchState true "Patch state"
// @Param state body PostState true "Patch state"
// @Success 200
// @Failure 404 {object} HTTPError
// @Failure 500 {object} HTTPError
// @Router /states/{uuid} [patch]
func (a API) PatchState(c echo.Context) error {
var req PatchState
// @Router /states/{uuid} [post]
func (a API) PostState(c echo.Context) error {
var req PostState
if err := c.Bind(&req); err != nil {
return echo.ErrBadRequest.WithInternal(err)
}
Expand All @@ -289,9 +290,15 @@ func (a API) PatchState(c echo.Context) error {
}
}

if req.Volume != nil {
if err := radio.SetVolume(ctx, rd, *req.Volume); err != nil {
return err
if req.Volume != nil || req.VolumeDelta != nil {
if req.Volume != nil {
if err := radio.SetVolume(ctx, rd, *req.Volume); err != nil {
return err
}
} else if req.VolumeDelta != nil {
if err := radio.ChangeVolume(ctx, rd, *req.VolumeDelta); err != nil {
return err
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func Router(a API, fs fs.FS) *echo.Echo {
apiStates := api.Group("/states/:uuid")
apiStates.Use(a.RadioMiddleware)
apiStates.GET("", a.GetState)
apiStates.PATCH("", a.PatchState)
apiStates.POST("", a.PostState)

api.GET("/ws", a.WS(upgrader()))
}
Expand Down
9 changes: 9 additions & 0 deletions internal/radio/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ func SetVolume(ctx context.Context, r hub.Radio, volume int) error {
})
}

func ChangeVolume(ctx context.Context, r hub.Radio, delta int) error {
s, err := GetState(ctx, r)
if err != nil {
return err
}

return SetVolume(ctx, r, delta+s.Volume)
}

func PlayPreset(ctx context.Context, r hub.Radio, preset int) error {
s, err := GetState(ctx, r)
if err != nil {
Expand Down
26 changes: 13 additions & 13 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import {
} from "./api";
import {
useDiscoverRadios,
usePatchState,
useUpdateState,
useRefreshRadioVolume,
useRefreshRadioSubscription,
useRadiosListQuery,
Expand Down Expand Up @@ -289,11 +289,11 @@ const RadioVolumeButtonGroup: Component<
state: StateState;
} & ClassProps
> = (props) => {
const statePatch = usePatchState(props.radioUUID);
const updateState = useUpdateState(props.radioUUID);
const refreshRadioVolume = useRefreshRadioVolume(props.radioUUID);

const changeVolume = (volumeChange: number) => {
void statePatch.mutate({ volume: props.state.volume + volumeChange });
void updateState.mutate({ volume_delta: volumeChange });
};

const refreshVolume = () => {
Expand All @@ -306,7 +306,7 @@ const RadioVolumeButtonGroup: Component<
fallback={
<DaisyButton
class={mergeClass("btn-error", props.class)}
loading={statePatch.loading()}
loading={updateState.loading()}
aria-label="Volume Muted"
>
<FaSolidVolumeOff size={ICON_SIZE} />
Expand All @@ -316,7 +316,7 @@ const RadioVolumeButtonGroup: Component<
<div class={mergeClass("btn-group flex-nowrap", props.class)}>
<DaisyButton
class="btn-info w-14"
loading={statePatch.loading()}
loading={updateState.loading()}
aria-label="Lower Volume"
onClick={[changeVolume, -5]}
>
Expand All @@ -332,7 +332,7 @@ const RadioVolumeButtonGroup: Component<
</DaisyButton>
<DaisyButton
class="btn-info w-14"
loading={statePatch.loading()}
loading={updateState.loading()}
aria-label="Raise Volume"
onClick={[changeVolume, 5]}
>
Expand All @@ -349,10 +349,10 @@ const RadioPowerButton: Component<
state: StateState;
} & ClassProps
> = (props) => {
const patchState = usePatchState(props.radioUUID);
const updateState = useUpdateState(props.radioUUID);

const togglePower = () => {
void patchState.mutate({
void updateState.mutate({
power: !props.state.power,
});
};
Expand All @@ -364,7 +364,7 @@ const RadioPowerButton: Component<
"btn-success": props.state.power,
"btn-error": !props.state.power,
}}
loading={patchState.loading()}
loading={updateState.loading()}
onClick={togglePower}
aria-label={"Power " + (props.state.power ? "On" : "Off")}
>
Expand All @@ -386,15 +386,15 @@ const RadioAudioSourceDropdown: Component<
state: StateState;
} & ClassProps
> = (props) => {
const statePatch = usePatchState(props.radioUUID);
const updateState = useUpdateState(props.radioUUID);
const [lastLoadingAudioSource, setLastLoadingAudioSource] = createSignal("");
const loadingAudioSource = (): string =>
statePatch.loading() ? lastLoadingAudioSource() : "";
updateState.loading() ? lastLoadingAudioSource() : "";

const setAudioSource = (audioSource: string) => {
batch(() => {
statePatch.cancel();
void statePatch.mutate({ audio_source: audioSource });
updateState.cancel();
void updateState.mutate({ audio_source: audioSource });
setLastLoadingAudioSource(audioSource);
});
};
Expand Down
13 changes: 7 additions & 6 deletions web/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ export interface HttpHTTPError {
message: string;
}

export interface HttpPatchState {
export interface HttpPostState {
audio_source?: string;
power?: boolean;
preset?: number;
volume?: number;
volume_delta?: number;
}

export interface ModelBuild {
Expand Down Expand Up @@ -548,14 +549,14 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
* No description
*
* @tags states
* @name StatesPartialUpdate
* @summary Patch state
* @request PATCH:/states/{uuid}
* @name StatesCreate
* @summary Update state
* @request POST:/states/{uuid}
*/
statesPartialUpdate: (uuid: string, state: HttpPatchState, params: RequestParams = {}) =>
statesCreate: (uuid: string, state: HttpPostState, params: RequestParams = {}) =>
this.request<void, HttpHTTPError>({
path: `/states/${uuid}`,
method: "PATCH",
method: "POST",
body: state,
type: ContentType.Json,
...params,
Expand Down
4 changes: 2 additions & 2 deletions web/src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from "solid-js";
import { type StatePreset, type StateState } from "../api";
import { DaisyButton } from "../Daisy";
import { usePatchState } from "../store";
import { useUpdateState } from "../store";
import { type ClassProps, mergeClass } from "../utils";

export const HomePage: Component<
Expand All @@ -19,7 +19,7 @@ export const HomePage: Component<
state: StateState;
} & ClassProps
> = (props) => {
const statePatch = usePatchState(props.radioUUID);
const statePatch = useUpdateState(props.radioUUID);
const [lastLoadingNumber, setLoadingNumber] = createSignal(-1);
const loadingNumber = (): number =>
statePatch.loading() ? lastLoadingNumber() : -1;
Expand Down
8 changes: 4 additions & 4 deletions web/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
} from "solid-js";
import {
Api,
type HttpPostState,
type ModelPreset,
type HttpPatchState,
type RequestParams,
} from "./api";
import { type ModelRadio } from "./api";
Expand Down Expand Up @@ -165,11 +165,11 @@ export const useRefreshRadioSubscription = (uuid: Accessor<string>) =>
);

// State update
export const usePatchState = (uuid: Accessor<string>) =>
export const useUpdateState = (uuid: Accessor<string>) =>
cancelWhen(
uuid,
createMutation((params, req: HttpPatchState) =>
api.states.statesPartialUpdate(uuid(), req, params)
createMutation((params, req: HttpPostState) =>
api.states.statesCreate(uuid(), req, params)
)
);

Expand Down

0 comments on commit 8e55f43

Please sign in to comment.