/** @module profile */
import * as Types from './versus/types.js';
const LOCAL_PROFILE_IMAGE_NAME_LOCATION = 'user_profile.image_name';
const LOCAL_PROFILE_IMAGE_CUSTOM_URL_LOCATION = 'user_profile.custom_image_url';
const LOCAL_PROFILE_USERNAME_LOCATION = 'user_profile.username';
const LOCAL_PROFILE_VOLUME_MUTE_LOCATION = 'user_profile.volume_mute';
const LOCAL_PROFILE_MUSIC_LEVEL_LOCATION = 'user_profile.music_level';
const LOCAL_PROFILE_SFX_LEVEL_LOCATION = 'user_profile.sfx_level';
const LOCAL_PROFILE_UUID_lOCATION = 'user_profile.uuid';
const DEFAULT_USERNAME = 'User';
const DEFAULT_MUTE = false;
const DEFAULT_MUSIC_VOLUME_LEVEL = 0.5;
const DEFAULT_SFX_VOLUME_LEVEL = 0.5;
/** @type { Record<ProfileImageName, string> } */
const LOCAL_PROFILE_IMAGE_STANDARD_URLS = {
default: './assets/images/profiles/default.svg',
duck: './assets/images/profiles/duck.svg',
elephant: './assets/images/profiles/elephant.svg',
fox: './assets/images/profiles/fox.svg',
lion: './assets/images/profiles/lion.svg',
walrus: './assets/images/profiles/walrus.svg',
};
export const LOCAL_PROFILE_IMAGE_CUSTOM_FLAG = 'custom_image';
export const UPDATE_VOLUME_LISTENER_NAME = 'volume-update';
/**
* @typedef { ('default'|'duck'|'elephant'|'fox'|'lion'|'walrus'|LOCAL_PROFILE_IMAGE_CUSTOM_FLAG) } ProfileImageName
*/
/**
* Fetches list of existing profile image name options; used to populate
* list of available options in settings menu
* @returns { ProfileImageName[] } list of names that can be selected by user
*/
export function getProfileImageNameOptions() {
return Object.keys(LOCAL_PROFILE_IMAGE_STANDARD_URLS);
} /* getProfileImageNameOptions */
/**
* Converts name of a profile image to an actual url; used to populate option lists
* in settings menu or pick url for opponent's icon in versus mode
* @param { ProfileImageName } profileImageName name of profile image, custom excluded
* @returns { string } url to profile image
*/
export function getProfileImageUrlFromName(profileImageName) {
// TODO: Handle custom image case for opponent user
return (
LOCAL_PROFILE_IMAGE_STANDARD_URLS[profileImageName] ??
LOCAL_PROFILE_IMAGE_STANDARD_URLS.default
);
} /* getProfileImageUrlFromName */
/**
* Saves valid profile image name, or custom (data) url, to local storage for
* access across sessions
* @param { ProfileImageName } profileImageName name of profile image, or custom flag if customUrl passed
* @param { { customUrl: string } } [options] customUrl corresponding to path if custom flag set
* @returns { boolean } true if saved successfully; otherwise false
*/
export function setProfileImage(profileImageName, { customUrl } = {}) {
// TODO: for custom context, consider case where image file size exceeds localstorage limit (x MB)
if (profileImageName === LOCAL_PROFILE_IMAGE_CUSTOM_FLAG) {
if (!customUrl) return false;
window.localStorage.setItem(
LOCAL_PROFILE_IMAGE_NAME_LOCATION,
LOCAL_PROFILE_IMAGE_CUSTOM_FLAG,
);
window.localStorage.setItem(
LOCAL_PROFILE_IMAGE_CUSTOM_URL_LOCATION,
customUrl,
);
return true;
}
if (!LOCAL_PROFILE_IMAGE_STANDARD_URLS[profileImageName]) {
return false;
}
window.localStorage.setItem(
LOCAL_PROFILE_IMAGE_NAME_LOCATION,
profileImageName,
);
return true;
} /* setProfileImageUrl */
/**
* Fetches profile image url from browser's local storage
* @returns { string } file path to saved user profile image
*/
export function getProfileImageUrl() {
const profileImageName = window.localStorage.getItem(
LOCAL_PROFILE_IMAGE_NAME_LOCATION,
);
if (profileImageName === LOCAL_PROFILE_IMAGE_CUSTOM_FLAG)
return window.localStorage.getItem(LOCAL_PROFILE_IMAGE_CUSTOM_URL_LOCATION);
return (
LOCAL_PROFILE_IMAGE_STANDARD_URLS[profileImageName] ??
LOCAL_PROFILE_IMAGE_STANDARD_URLS.default
);
} /* getProfileImageUrl */
/**
* Fetches name of profile image from browser's local storage
* @returns { ProfileImageName } name of profile image selected
*/
export function getProfileImageName() {
return (
window.localStorage.getItem(LOCAL_PROFILE_IMAGE_NAME_LOCATION) ?? 'default'
);
} /* getProfileImageName */
/**
* Saves valid username to local storage for access across sessions
* @param { string } username valid (nonempty) username
* @returns { boolean } true if saved successfully; otherwise false
*/
export function setUsername(username) {
if (!username) return false;
window.localStorage.setItem(LOCAL_PROFILE_USERNAME_LOCATION, username);
return true;
} /* setUsername */
/**
* Fetches username from browser's local storage
* @returns { string } saved username
*/
export function getUsername() {
return (
window.localStorage.getItem(LOCAL_PROFILE_USERNAME_LOCATION) ??
DEFAULT_USERNAME
);
} /* getUsername */
/**
* Saves mute setting to local storage for access across sessions
* @param { boolean } isMute true if volume should be muted; otherwise false
* @returns { boolean } true if saved successfully; otherwise false
*/
export function setIsMute(isMute) {
if (typeof isMute !== 'boolean') return false;
window.localStorage.setItem(LOCAL_PROFILE_VOLUME_MUTE_LOCATION, isMute);
window.dispatchEvent(new Event(UPDATE_VOLUME_LISTENER_NAME));
return true;
} /* setIsMute */
/**
* Fetches mute setting from browser's local storage
* @returns { boolean } saved mute status; true if muted and false otherwise
*/
export function getIsMute() {
const proposedIsMute = window.localStorage.getItem(
LOCAL_PROFILE_VOLUME_MUTE_LOCATION,
);
return ['true', 'false'].includes(proposedIsMute)
? proposedIsMute === 'true'
: DEFAULT_MUTE;
} /* getIsMute */
/**
* Saves music volume level setting to local storage for access across sessions
* @param { number } volumeLevel volume level in range [0, 1]
* @returns { boolean } true if saved successfully; false otherwise
*/
export function setMusicVolumeLevel(volumeLevel) {
if (isNaN(volumeLevel) || volumeLevel < 0 || volumeLevel > 1) return false;
window.localStorage.setItem(LOCAL_PROFILE_MUSIC_LEVEL_LOCATION, volumeLevel);
window.dispatchEvent(new Event(UPDATE_VOLUME_LISTENER_NAME));
return true;
} /* setMusicVolumeLevel */
/**
* Saves special effects volume level setting to local storage for access across sessions
* @param { number } volumeLevel volume level in range [0, 1]
* @returns { boolean } true if saved successfully; false otherwise
*/
export function setSFXVolumeLevel(volumeLevel) {
if (isNaN(volumeLevel) || volumeLevel < 0 || volumeLevel > 1) return false;
window.localStorage.setItem(LOCAL_PROFILE_SFX_LEVEL_LOCATION, volumeLevel);
window.dispatchEvent(new Event(UPDATE_VOLUME_LISTENER_NAME));
return true;
} /* setSFXVolumeLevel */
/**
* Fetches current music volume from browser's local storage
* @returns { number } currently saved music volume in range [0, 1]
*/
export function getMusicVolumeLevel() {
return +(
window.localStorage.getItem(LOCAL_PROFILE_MUSIC_LEVEL_LOCATION) ??
DEFAULT_MUSIC_VOLUME_LEVEL
);
} /* getMusicVolumeLevel */
/**
* Fetches current special effects volume from browser's local storage
* @returns { number } currently saved SFX volume in range [0, 1]
*/
export function getSFXVolumeLevel() {
return +(
window.localStorage.getItem(LOCAL_PROFILE_SFX_LEVEL_LOCATION) ??
DEFAULT_SFX_VOLUME_LEVEL
);
} /* getSFXVolumeLevel */
/**
* Attaches UUID sent from server to profile instance by saving it to browser's
* session storage; UUIDs are set on a per-instance basis
* @param { Types.UUID } playerUUID UUID sent from server
* @returns { boolean } true if saved successfully; otherwise false
*/
export function setPlayerUUID(playerUUID) {
if (typeof playerUUID !== 'string' || playerUUID.length == 0) return false;
window.sessionStorage.setItem(LOCAL_PROFILE_UUID_lOCATION, playerUUID);
return true;
} /* setPlayerUUID */
/**
* Fetches previously-set player UUID from browser's session storage; UUID will be
* invalid if fetched after game instance has ended
* @returns { Types.UUID } last UUID sent from the server to the client
*/
export function getPlayerUUID() {
return window.sessionStorage.getItem(LOCAL_PROFILE_UUID_lOCATION);
} /* getPlayerUUID */
/**
* @returns { Types.ClientToServerProfile } object containing locally saved profile data
*/
export function createProfileObject() {
return {
username: getUsername(),
profileImageName: getProfileImageName(),
};
} /* createSelfProfile */