Преглед изворни кода

feat: active state in status bar

Fela Maslen пре 4 година
родитељ
комит
d47b4623b4

+ 2 - 1
gmus-web/src/components/ui/cmus/views/status.tsx

@@ -1,6 +1,6 @@
 import React, { useContext } from 'react';
 import { StateContext } from '../../../../context/state';
-import { isMaster } from '../../../../selectors';
+import { isActiveClient, isMaster } from '../../../../selectors';
 
 import { MusicPlayer, Song } from '../../../../types';
 import { formatTime } from '../../../../utils/time';
@@ -60,6 +60,7 @@ export const PlayerStatus: React.FC<Props> = ({ song, ...props }) => {
         </Styled.Time>
         <Styled.ClientName>
           {state.myClientName} [{isMaster(state) ? 'Master' : 'Slave'}]
+          {isActiveClient(state) ? '🔊' : '🔈'}
         </Styled.ClientName>
         &nbsp;
         <StatusIcon {...props} />

+ 52 - 4
gmus-web/src/selectors.spec.ts

@@ -1,8 +1,8 @@
 import { ActionTypeRemote, stateSet } from './actions';
 import { GlobalState, initialState } from './reducer';
-import { isFromOurselves, isMaster, willBeMaster } from './selectors';
+import { isActiveClient, isFromOurselves, isMaster, willBeMaster } from './selectors';
 
-describe(isMaster.name, () => {
+describe('isMaster', () => {
   describe('when the master player is the current client', () => {
     it('should return true', () => {
       expect.assertions(1);
@@ -40,7 +40,55 @@ describe(isMaster.name, () => {
   });
 });
 
-describe(isFromOurselves.name, () => {
+describe('isActiveClient', () => {
+  describe('when the client is master', () => {
+    it('should return true', () => {
+      expect.assertions(1);
+      expect(
+        isActiveClient({
+          player: { ...initialState.player, master: 'my-client-name', activeClients: [] },
+          myClientName: 'my-client-name',
+        }),
+      ).toBe(true);
+    });
+  });
+
+  describe('when the client is a slave', () => {
+    describe('when the client is in the active clients list', () => {
+      it('should return true', () => {
+        expect.assertions(1);
+        expect(
+          isActiveClient({
+            player: {
+              ...initialState.player,
+              master: 'some-other-client',
+              activeClients: ['my-client-name'],
+            },
+            myClientName: 'my-client-name',
+          }),
+        ).toBe(true);
+      });
+    });
+
+    describe('when the client is not in the active clients list', () => {
+      it('should return false', () => {
+        expect.assertions(1);
+        expect(
+          isActiveClient({
+            player: {
+              ...initialState.player,
+              master: 'some-other-client',
+              activeClients: ['different-client-name'],
+            },
+            myClientName: 'my-client-name',
+          }),
+        ).toBe(false);
+      });
+    });
+  });
+});
+
+describe('isFromOurselves', () => {
   describe('when an action was dispatched from the current client', () => {
     it('should return true', () => {
       expect.assertions(1);
@@ -90,7 +138,7 @@ describe(isFromOurselves.name, () => {
   });
 });
 
-describe(willBeMaster.name, () => {
+describe('willBeMaster', () => {
   describe('when the action will cause the current client to be master', () => {
     it('should return true', () => {
       expect.assertions(1);

+ 3 - 0
gmus-web/src/selectors.ts

@@ -4,6 +4,9 @@ import { GlobalState } from './reducer/types';
 export const isMaster = (state: Pick<GlobalState, 'player' | 'myClientName'>): boolean =>
   state.player.master === state.myClientName;
 
+export const isActiveClient = (state: Pick<GlobalState, 'player' | 'myClientName'>): boolean =>
+  isMaster(state) || state.player.activeClients.includes(state.myClientName);
+
 export const isFromOurselves = (
   state: Pick<GlobalState, 'myClientName'>,
   action: ActionRemote,