Skip to content
This repository has been archived by the owner on Aug 27, 2024. It is now read-only.

Commit

Permalink
Merge pull request #158 from CptWesley/forbidden-feature-disabling
Browse files Browse the repository at this point in the history
  • Loading branch information
CptWesley authored Nov 17, 2021
2 parents 8a184e0 + e70fde3 commit 0c2a083
Show file tree
Hide file tree
Showing 15 changed files with 192 additions and 50 deletions.
2 changes: 1 addition & 1 deletion overwolf/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cptwesley-minimap",
"version": "1.2.0",
"version": "1.3.0",
"description": "",
"main": "index.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion overwolf/public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"meta": {
"name": "CptWesley's Minimap",
"author": "Wesley Baartman",
"version": "1.2.0",
"version": "1.3.0",
"minimum-overwolf-version": "0.92.300.0",
"description": "Open-source minimap for Amazon's New World.",
"dock_button_title": "CptWesleys Minimap",
Expand Down
48 changes: 48 additions & 0 deletions overwolf/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import produce from 'immer';
import React, { useContext, useEffect } from 'react';
import { AppContext } from './contexts/AppContext';
import { getDefaultIconSettings } from './logic/markers';
import { deconstructIconStorageKey, getStorageKeyScope, load, loadIconConfiguration, scopedSettings, simpleStorageDefaultSettings, SimpleStorageSetting } from './logic/storage';
import Minimap from './Minimap';
import { makeStyles } from './theme';
import Welcome from './Welcome';
Expand Down Expand Up @@ -33,6 +35,52 @@ export default function App() {
});
}, []);

useEffect(() => {
function handleStorageEvent(e: StorageEvent) {
if (!e.key || !e.newValue) { return; }

const [keyScope, identifier] = getStorageKeyScope(e.key);
if (keyScope === NWMM_APP_WINDOW && scopedSettings.includes(identifier as keyof SimpleStorageSetting)) {
// The setting is scoped to the current window, and is listed as a scoped setting
context.update({ [identifier as keyof SimpleStorageSetting]: load(identifier as keyof SimpleStorageSetting) });
} else if (keyScope === 'icon') {
// It is an icon setting. First, determine if it's just a category, or a category and an icon
const iconSetting = deconstructIconStorageKey(identifier);
if (iconSetting) {
const { category, type, property } = iconSetting;
if (type) {
// It is a category and type. If the iconSettings are loaded, and the category and type exist,
// produce a new iconSettings with the category.types.type value set to the new setting value.
context.update(prev => produce(prev, draft => {
const setting = draft.iconSettings?.categories[category]?.types[type];
if (setting) {
setting[property] = loadIconConfiguration(category, type, property);
}
}));
} else {
// It is just a category. If the iconSettings are loaded, and the category exists, produce a new iconSettings
// with the category value set to the new setting value.
context.update(prev => produce(prev, draft => {
const setting = draft.iconSettings?.categories[category];
if (setting) {
setting[property] = loadIconConfiguration(category, type, property);
}
}));
}
}
} else if (keyScope === undefined && simpleStorageDefaultSettings.hasOwnProperty(identifier) && !scopedSettings.includes(identifier as keyof SimpleStorageSetting)) {
// The setting is not scoped to the current window, and exists, but is not listed as a scoped setting.
context.update({ [identifier as keyof SimpleStorageSetting]: load(identifier as keyof SimpleStorageSetting) });
}
}

window.addEventListener('storage', handleStorageEvent);

return () => {
window.removeEventListener('storage', handleStorageEvent);
};
}, []);

if (!context.gameRunning) {
return <Welcome />;
}
Expand Down
53 changes: 9 additions & 44 deletions overwolf/src/Frame.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import '@/style/lato-fonts.css';
import clsx from 'clsx';
import produce from 'immer';
import React, { useCallback, useEffect, useState } from 'react';
import { GlobalStyles } from 'tss-react';
import App from './App';
import AppSettings from './AppSettings/AppSettings';
import { AppContext, AppContextSettings, IAppContext, loadAppContextSettings } from './contexts/AppContext';
import { deconstructIconStorageKey, getStorageKeyScope, load, loadIconConfiguration, scopedSettings, simpleStorageDefaultSettings, SimpleStorageSetting } from './logic/storage';
import InAppNotices from './InAppNotices';
import { getBackgroundController } from './OverwolfWindows/background/background';
import { makeStyles, theme } from './theme';

Expand Down Expand Up @@ -46,54 +45,19 @@ export default function Frame(props: IProps) {
const [appContextSettings, setAppContextSettings] = useState<AppContextSettings>(loadAppContextSettings);
const [gameRunning, setGameRunning] = useState(backgroundController.gameRunning);

const updateAppContext = useCallback((e: Partial<AppContextSettings>) => setAppContextSettings(prev => ({ ...prev, ...e })), []);
const updateAppContext = useCallback((e: React.SetStateAction<Partial<AppContextSettings>>) => {
if (typeof e === 'function') {
setAppContextSettings(prev => ({ ...prev, ...e(prev) }));
} else {
setAppContextSettings(prev => ({ ...prev, ...e }));
}
}, []);
const toggleFrameMenu = useCallback(() => setAppSettingsVisible(prev => !prev), []);

useEffect(() => {
function handleStorageEvent(e: StorageEvent) {
if (!e.key || !e.newValue) { return; }

const [keyScope, identifier] = getStorageKeyScope(e.key);
if (keyScope === NWMM_APP_WINDOW && scopedSettings.includes(identifier as keyof SimpleStorageSetting)) {
// The setting is scoped to the current window, and is listed as a scoped setting
updateAppContext({ [identifier as keyof SimpleStorageSetting]: load(identifier as keyof SimpleStorageSetting) });
} else if (keyScope === 'icon') {
// It is an icon setting. First, determine if it's just a category, or a category and an icon
const iconSetting = deconstructIconStorageKey(identifier);
if (iconSetting) {
const { category, type, property } = iconSetting;
if (type) {
// It is a category and type. If the iconSettings are loaded, and the category and type exist,
// produce a new iconSettings with the category.types.type value set to the new setting value.
setAppContextSettings(prev => produce(prev, draft => {
const setting = draft.iconSettings?.categories[category]?.types[type];
if (setting) {
setting[property] = loadIconConfiguration(category, type, property);
}
}));
} else {
// It is just a category. If the iconSettings are loaded, and the category exists, produce a new iconSettings
// with the category value set to the new setting value.
setAppContextSettings(prev => produce(prev, draft => {
const setting = draft.iconSettings?.categories[category];
if (setting) {
setting[property] = loadIconConfiguration(category, type, property);
}
}));
}
}
} else if (keyScope === undefined && simpleStorageDefaultSettings.hasOwnProperty(identifier) && !scopedSettings.includes(identifier as keyof SimpleStorageSetting)) {
// The setting is not scoped to the current window, and exists, but is not listed as a scoped setting.
updateAppContext({ [identifier as keyof SimpleStorageSetting]: load(identifier as keyof SimpleStorageSetting) });
}
}

window.addEventListener('storage', handleStorageEvent);

const gameRunningListenRegistration = backgroundController.listenOnGameRunningChange(setGameRunning, window);

return () => {
window.removeEventListener('storage', handleStorageEvent);
gameRunningListenRegistration();
};
}, []);
Expand Down Expand Up @@ -157,6 +121,7 @@ export default function Frame(props: IProps) {
onClose={() => setAppSettingsVisible(false)}
/>
{header}
<InAppNotices />
<App />
</div>
</AppContext.Provider>
Expand Down
89 changes: 89 additions & 0 deletions overwolf/src/InAppNotices.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import Button from './Button';
import { globalLayers } from './globalLayers';
import { makeStyles } from './theme';

const notices = {
'5289534c-bf5a-4d5c-8678-254ab8bdefe3': 'Due to requests from Amazon Games, several features of this application have been disabled until further notice. These features include:\n\n- Markers on the map\n- Navigation\n- Displaying friends.\n\nWe will consider enabling them when the APIs we need to display the correct information are available.',
};

function loadNoticeRead(notice: keyof typeof notices) {
return localStorage.getItem(`notice::${notice}`) === true.toString();
}

function storeNoticeRead(notice: keyof typeof notices) {
localStorage.setItem(`notice::${notice}`, true.toString());
}

const useStyles = makeStyles()(theme => ({
root: {
background: '#343f6e',
color: theme.color,
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: globalLayers.inAppAnnouncement,

display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: theme.spacing(1),
gap: theme.spacing(1),
},
notices: {
flexGrow: 1,
maxWidth: '100%',
width: 500,
marginTop: theme.spacing(5),
overflow: 'auto',
},
notice: {
padding: theme.spacing(1),

'&:not(:last-child)': {
borderBottom: `1px solid ${theme.color}`,
},
},
noticeText: {
whiteSpace: 'pre-line',
},
actions: {

},
}));

export default function InAppNotices() {
const { classes } = useStyles();
const { t } = useTranslation();

const forceRerender = useState(0)[1];
const noticeEntries = Object.entries(notices) as [keyof typeof notices, string][];
const unreadNotices = noticeEntries.filter(ne => !loadNoticeRead(ne[0]));

if (unreadNotices.length === 0) {
return null;
}

function handleClose() {
for (const unreadNotice of unreadNotices) {
storeNoticeRead(unreadNotice[0]);
}
forceRerender(value => value + 1);
}

return <div className={classes.root}>
<div className={classes.notices}>
{unreadNotices.map(n => <div key={n[0]} className={classes.notice}>
<p className={classes.noticeText}>
{n[1]}
</p>
</div>)}
</div>
<div className={classes.actions}>
<Button onClick={handleClose}>{t('close')}</Button>
</div>
</div>;
}
5 changes: 5 additions & 0 deletions overwolf/src/Minimap/drawMapFriends.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { canDrawFriends } from '@/logic/featureFlags';
import { FriendData } from '@/logic/friends';
import { worldCoordinateToCanvas } from '@/logic/tiles';
import { rotateAround } from '@/logic/util';
Expand All @@ -7,6 +8,10 @@ import { MapIconRendererParameters, MapRendererParameters } from './useMinimapRe
const sliceRotationOffset = -Math.PI / 2;

export default function drawMapFriends(params: MapRendererParameters, iconParams: MapIconRendererParameters, friends: FriendData[]) {
if (!canDrawFriends) {
return;
}

const {
context: ctx,
center,
Expand Down
5 changes: 5 additions & 0 deletions overwolf/src/Minimap/drawMapLabels.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { canDrawMarkers } from '@/logic/featureFlags';
import { getIconName } from '@/logic/icons';
import { getMarkers } from '@/logic/markers';
import { canvasCoordinateToWorld, getTileCoordinatesForWorldCoordinate, worldCoordinateToCanvas } from '@/logic/tiles';
Expand All @@ -22,6 +23,10 @@ export default function drawMapLabel(ctx: CanvasRenderingContext2D, marker: Mark
}

export function drawMapHoverLabel(mousePos: Vector2, lastDrawCache: LastDrawParameters, canvas: React.RefObject<HTMLCanvasElement>, iconScale: number) {
if (!canDrawMarkers) {
return;
}

if (!canvas.current) {
return;
}
Expand Down
5 changes: 5 additions & 0 deletions overwolf/src/Minimap/drawMapMarkers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { canDrawMarkers } from '@/logic/featureFlags';
import { worldCoordinateToCanvas } from '@/logic/tiles';
import { rotateAround } from '@/logic/util';
import drawMapLabel from '@/Minimap/drawMapLabels';
import { MapIconRendererParameters, MapRendererParameters } from './useMinimapRenderer';

export default function drawMapMarkers(params: MapRendererParameters, iconParams: MapIconRendererParameters, markers: Marker[]) {
if (!canDrawMarkers) {
return;
}

const {
context: ctx,
center,
Expand Down
7 changes: 6 additions & 1 deletion overwolf/src/Minimap/drawMapNavigation.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { canDrawNavigation } from '@/logic/featureFlags';
import { getNavPath } from '@/logic/navigation/navigation';
import { worldCoordinateToCanvas } from '@/logic/tiles';
import { rotateAround } from '@/logic/util';
import setLineStyle from './setLineStyle';
import { MapRendererParameters } from './useMinimapRenderer';

export default function drawMapNavigation(params: MapRendererParameters) {
export default function drawMapNavigation(params: MapRendererParameters): Vector2 | undefined {
if (!canDrawNavigation) {
return undefined;
}

const {
context: ctx,
center,
Expand Down
5 changes: 5 additions & 0 deletions overwolf/src/Minimap/drawMapNavigationTarget.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { canDrawNavigation } from '@/logic/featureFlags';
import { MapIconRendererParameters, MapRendererParameters } from './useMinimapRenderer';

export default function drawMapNavigationTarget(params: MapRendererParameters, iconParams: MapIconRendererParameters, target: Vector2 | undefined) {
if (!canDrawNavigation) {
return;
}

if (!target) {
return;
}
Expand Down
6 changes: 5 additions & 1 deletion overwolf/src/MinimapToolbarIconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const useStyles = makeStyles()(theme => ({
pointerEvents: 'none', // makes tooltips behave nicer
},

'&:hover': {
'&:hover:not(:disabled)': {
background: theme.buttonBackgroundHover,
},

Expand All @@ -41,6 +41,10 @@ const useStyles = makeStyles()(theme => ({
'&:active': {
background: theme.buttonBackgroundPress,
},

'&:disabled': {
opacity: 0.5,
},
},
selected: {
// background: theme.buttonBackgroundHover,
Expand Down
2 changes: 2 additions & 0 deletions overwolf/src/MinimapToolbars.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import DragIcon from './Icons/DragIcon';
import RecenterIcon from './Icons/RecenterIcon';
import ZoomInIcon from './Icons/ZoomInIcon';
import ZoomOutIcon from './Icons/ZoomOutIcon';
import { canDrawNavigation } from './logic/featureFlags';
import MinimapToolbar from './MinimapToolbar';
import MinimapToolbarIconButton from './MinimapToolbarIconButton';
import { makeStyles } from './theme';
Expand Down Expand Up @@ -90,6 +91,7 @@ export default function MinimapToolbars(props: IProps) {
isSelected={interactionMode === 'destination'}
onClick={() => setInteractionMode('destination')}
title={t('minimap.mode_destination')}
disabled={!canDrawNavigation}
>
<DestinationIcon />
</MinimapToolbarIconButton>
Expand Down
2 changes: 1 addition & 1 deletion overwolf/src/contexts/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type AppContextSettings = SimpleStorageSetting & {

export interface IAppContext {
settings: AppContextSettings;
update: (delta: Partial<AppContextSettings>) => void;
update: (delta: React.SetStateAction<Partial<AppContextSettings>>) => void;
toggleFrameMenu: () => void;
gameRunning: boolean;
isTransparentSurface: boolean | undefined;
Expand Down
3 changes: 2 additions & 1 deletion overwolf/src/globalLayers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export const globalLayers = {
frameMenu: 975,
frameMenu: 900,
header: 950,
minimapCanvas: 10,
minimapHoverCanvas: 11,
minimapCacheStatus: 12,
minimapToolbar: 15,
resizeGrips: 999,
inAppAnnouncement: 940,
};
8 changes: 8 additions & 0 deletions overwolf/src/logic/featureFlags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const forbiddenFeaturesKey = 'DANGER_ENABLE_FORBIDDEN_FEATURES';

const enableForbiddenFeatures = localStorage.getItem(forbiddenFeaturesKey) === true.toString();

export const canDrawPlayer = true;
export const canDrawMarkers = enableForbiddenFeatures;
export const canDrawFriends = enableForbiddenFeatures;
export const canDrawNavigation = enableForbiddenFeatures;

0 comments on commit 0c2a083

Please sign in to comment.