All user data for FoundryVTT. Includes worlds, systems, modules, and any asset in the "foundryuserdata" directory. Does NOT include the FoundryVTT installation itself.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1 lines
179 KiB

{"version":3,"file":"main.js","mappings":"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","sources":["webpack:///../common/Settings.ts","webpack:///../common/libWrapperShared.ts","webpack:///./src/Util.ts","webpack:///./src/archive/DFChatArchive.ts","webpack:///./src/archive/DFChatArchiveManager.ts","webpack:///./src/archive/DFChatArchiveNew.ts","webpack:///./src/archive/DFChatArchiveViewer.ts","webpack:///./src/archive/df-chat-archive.ts","webpack:///./src/chat-time/chat-time.ts","webpack:///./src/edit/DFChatEditor.ts","webpack:///./src/edit/df-chat-edit.ts","webpack:///./src/font-size/font-size.ts","webpack:///./src/logger/DFAdventureLogConfig.ts","webpack:///./src/logger/DFAdventureLogProcessor.ts","webpack:///./src/logger/df-adventure-log.ts","webpack:///./src/merge/chat-merge.ts","webpack:///./src/player-color/PlayerColor.ts","webpack:///./src/privacy/df-chat-privacy.ts","webpack:///./src/scroll-manage/ChatHistoryOptimizer.ts","webpack:///./src/scroll-manage/scroll-manage.ts","webpack:///./src/send/send-button.ts","webpack:///./src/whisper-trunc/whisper-trunc.ts","webpack:///webpack/bootstrap","webpack:///webpack/runtime/define property getters","webpack:///webpack/runtime/hasOwnProperty shorthand","webpack:///webpack/runtime/make namespace object","webpack:///./src/df-chat-enhance.ts"],"sourcesContent":["\ndeclare global {\n\tinterface LenientGlobalVariableTypes {\n\t\tgame: never;\n\t\tcanvas: never;\n\t}\n\tinterface String {\n\t\t/** Localizes the string via the global `game.i18n.localize()` function. */\n\t\tlocalize(): string\n\t}\n\ttype AnyFunction = (...args: any) => any;\n}\n\nexport default class SETTINGS {\n\tstatic MOD_NAME: string;\n\tstatic init(moduleName: string) {\n\t\tthis.MOD_NAME = moduleName;\n\t\tif (!String.prototype.localize) {\n\t\t\tString.prototype.localize = function () {\n\t\t\t\treturn game.i18n.localize(this.valueOf());\n\t\t\t};\n\t\t}\n\t}\n\tstatic register<T>(key: string, config: ClientSettings.PartialSettingConfig<T>) { game.settings.register(SETTINGS.MOD_NAME, key, config); }\n\tstatic registerMenu(key: string, config: ClientSettings.PartialSettingSubmenuConfig) { game.settings.registerMenu(SETTINGS.MOD_NAME, key, config); }\n\tstatic get<T>(key: string): T { return <T>game.settings.get(SETTINGS.MOD_NAME, key); }\n\tstatic async set<T>(key: string, value: T): Promise<T> { return await game.settings.set(SETTINGS.MOD_NAME, key, value); }\n\tstatic default<T>(key: string): T { return <T>game.settings.settings.get(SETTINGS.MOD_NAME + '.' + key).default; }\n\t/** helper for referencing a Typed constructor for the `type` field of a setting { type: SETTINGS.typeOf<MyClass>() } */\n\tstatic typeOf<T>(): ConstructorOf<T> { return Object as any; }\n}\n","import SETTINGS from \"./Settings\";\n\ntype Wrapper = (...args: any) => unknown;\ntype Handler = (wrapped: Wrapper, ...args: any) => unknown;\n\nclass Registration {\n\tnextId = 0;\n\twrappers = new Map<number, Handler>();\n\n\thandler(context: any, wrapped: Wrapper, ...args: any): Promise<unknown> | unknown {\n\t\tlet current = wrapped;\n\t\tfor (const wrapper of this.wrappers.values()) {\n\t\t\tconst next = current;\n\t\t\tcurrent = (...args: any) => wrapper.call(context, next, ...args);\n\t\t}\n\t\treturn current.call(context, ...args);\n\t}\n}\n\nexport default class libWrapperShared {\n\tprivate static registrations = new Map<string, Registration>();\n\n\tstatic register(target: string, handler: Handler) {\n\t\tlet registration = this.registrations.get(target);\n\t\tif (!registration) {\n\t\t\tregistration = new Registration();\n\t\t\tlibWrapper.register(SETTINGS.MOD_NAME, target,\n\t\t\t\tfunction (this: any, wrapped: Wrapper, ...args: any) { return registration.handler(this, wrapped, ...args); }, 'WRAPPER');\n\t\t\tthis.registrations.set(target, registration);\n\t\t}\n\t\tconst id = registration.nextId++;\n\t\tregistration.wrappers.set(id, handler);\n\t\treturn id;\n\t}\n\n\tstatic unregister(target: string, id: number): boolean {\n\t\tconst registration = this.registrations.get(target);\n\t\tif (!registration) return false;\n\t\tregistration.wrappers.delete(id);\n\t\tif (registration.wrappers.size === 0) {\n\t\t\tlibWrapper.unregister(SETTINGS.MOD_NAME, target, false);\n\t\t\tthis.registrations.delete(target);\n\t\t}\n\t\treturn true;\n\t}\n}","export default class UTIL {\n\tstatic async requestReload() {\n\t\tif (await Dialog.confirm({\n\t\t\ttitle: \"DF_CHAT_ENHANCE.ReloadGameTitle\".localize(),\n\t\t\tcontent: \"DF_CHAT_ENHANCE.ReloadGameContent\".localize(),\n\t\t\tdefaultYes: true\n\t\t})) {\n\t\t\twindow.location.reload();\n\t\t}\n\t}\n\n\tstatic reloadChatLog() {\n\t\t// @ts-expect-error\n\t\tui.chat._lastId = null;\n\t\tui.chat._state = Application.RENDER_STATES.NONE;\n\t\tui.chat.render(true);\n\t}\n}","import { ChatMessageData } from \"@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs\";\nimport SETTINGS from \"../../../common/Settings\";\n\nexport interface DFChatArchiveEntry {\n\tid: number;\n\tname: string;\n\tvisible: boolean;\n\tfilename: string;\n\tfilepath: string;\n}\n\n\nclass ArchiveFolderMenu extends FormApplication {\n\tstatic get defaultOptions() {\n\t\treturn mergeObject(FormApplication.defaultOptions as Partial<FormApplicationOptions>, {\n\t\t\twidth: 400,\n\t\t\theight: 125,\n\t\t\tresizable: false,\n\t\t\tminimizable: false,\n\t\t\ttitle: 'DF_CHAT_ARCHIVE.Settings.ArchiveFolder_Name',\n\t\t\ttemplate: \"modules/df-chat-enhance/templates/archive-folder.hbs\",\n\t\t\tsubmitOnClose: false,\n\t\t\tsubmitOnChange: false,\n\t\t\tcloseOnSubmit: true\n\t\t}) as FormApplicationOptions;\n\t}\n\n\tprivate folder = SETTINGS.get<string>(DFChatArchive.PREF_FOLDER);\n\tprivate source = SETTINGS.get<string>(DFChatArchive.PREF_FOLDER_SOURCE);\n\n\tgetData(_options: any): any {\n\t\treturn { path: this.folder };\n\t}\n\n\tasync _renderInner(data: any): Promise<JQuery<HTMLElement>> {\n\t\tconst html = await super._renderInner(data);\n\t\tconst input = html.find('input#dfce-ca-folder-path')[0] as HTMLInputElement;\n\t\thtml.find('label>button').on('click', async event => {\n\t\t\tevent.preventDefault();\n\t\t\tconst fp = new FilePicker(<any>{\n\t\t\t\ttitle: 'DF_CHAT_ARCHIVE.Settings.ArchiveFolder_Name',\n\t\t\t\ttype: 'folder',\n\t\t\t\tfield: input,\n\t\t\t\tcallback: async (path: string) => {\n\t\t\t\t\tthis.source = fp.activeSource;\n\t\t\t\t\tthis.folder = path;\n\t\t\t\t},\n\t\t\t\tbutton: event.currentTarget\n\t\t\t});\n\t\t\tawait fp.browse(SETTINGS.get(DFChatArchive.PREF_FOLDER));\n\t\t});\n\t\treturn html;\n\t}\n\tprotected async _updateObject() {\n\t\tawait SETTINGS.set<string>(DFChatArchive.PREF_FOLDER, this.folder);\n\t\tawait SETTINGS.set<string>(DFChatArchive.PREF_FOLDER_SOURCE, this.source);\n\t}\n}\n\nexport class DFChatArchive {\n\tprivate static readonly PREF_LOGS = 'logs';\n\tprivate static readonly PREF_CID = 'currentId';\n\tstatic readonly PREF_FOLDER = 'archiveFolder';\n\tstatic readonly PREF_FOLDER_SOURCE = 'archiveFolderSource';\n\tprivate static readonly PREF_FOLDER_MENU = 'archiveFolderMenu';\n\tprivate static _updateListener: () => void = null;\n\n\tprivate static get DATA_FOLDER(): FilePicker.SourceType { return SETTINGS.get(DFChatArchive.PREF_FOLDER_SOURCE); }\n\n\tstatic setUpdateListener(listener: () => void) {\n\t\tthis._updateListener = listener;\n\t}\n\n\tstatic registerSettings() {\n\t\tSETTINGS.register(this.PREF_LOGS, {\n\t\t\tscope: 'world',\n\t\t\tconfig: false,\n\t\t\ttype: Object,\n\t\t\tdefault: [],\n\t\t\tonChange: () => {\n\t\t\t\tif (this._updateListener != null)\n\t\t\t\t\tthis._updateListener();\n\t\t\t}\n\t\t});\n\t\tSETTINGS.register(this.PREF_CID, {\n\t\t\tscope: 'world',\n\t\t\tconfig: false,\n\t\t\ttype: Number,\n\t\t\tdefault: 0\n\t\t});\n\n\t\tSETTINGS.registerMenu(this.PREF_FOLDER_MENU, {\n\t\t\tlabel: 'DF_CHAT_ARCHIVE.Settings.ArchiveFolder_Name',\n\t\t\thint: 'DF_CHAT_ARCHIVE.Settings.ArchiveFolder_Hint',\n\t\t\trestricted: true,\n\t\t\ttype: <any>ArchiveFolderMenu\n\t\t});\n\n\t\tSETTINGS.register(this.PREF_FOLDER, {\n\t\t\tscope: 'world',\n\t\t\tconfig: false,\n\t\t\ttype: String,\n\t\t\tdefault: `worlds/${game.world.id}/chat-archive`,\n\t\t\tonChange: async () => {\n\t\t\t\tawait this.createArchiveFolderIfMissing();\n\t\t\t\tif (this._updateListener != null)\n\t\t\t\t\tthis._updateListener();\n\t\t\t}\n\t\t});\n\t\tSETTINGS.register(this.PREF_FOLDER_SOURCE, {\n\t\t\tscope: 'world',\n\t\t\tconfig: false,\n\t\t\ttype: String,\n\t\t\tdefault: 'data',\n\t\t});\n\t\tthis.createArchiveFolderIfMissing();\n\t}\n\n\tprivate static async createArchiveFolderIfMissing() {\n\t\tconst folder: string = SETTINGS.get(this.PREF_FOLDER);\n\t\tawait FilePicker.browse(this.DATA_FOLDER, folder)\n\t\t\t.catch(async _ => {\n\t\t\t\tif (!await FilePicker.createDirectory(this.DATA_FOLDER, folder, {}))\n\t\t\t\t\tthrow new Error('Could not access the archive folder: ' + folder);\n\t\t\t});\n\t}\n\n\tstatic getLogs(): DFChatArchiveEntry[] { return SETTINGS.get<DFChatArchiveEntry[]>(this.PREF_LOGS); }\n\tstatic getArchive(id: number): DFChatArchiveEntry { return this.getLogs().find(x => x.id == id); }\n\tstatic exists(id: number): boolean { return !!this.getLogs().find(x => x.id == id); }\n\n\tprivate static async _generateChatArchiveFile(id: number, name: string, chats: ChatMessage[] | ChatMessageData[], visible: boolean): Promise<DFChatArchiveEntry> {\n\t\t// Get the folder path\n\t\tconst folderPath = SETTINGS.get<string>(this.PREF_FOLDER);\n\t\t// Replace special characters in name to underscores\n\t\tconst safeName = name.replace(/[^ a-z0-9-_()[\\]<>]/gi, '_');\n\t\t// Generate the system safe filename\n\t\tconst fileName = encodeURI(`${id}_${safeName}.json`);\n\t\t// Create the File and contents\n\t\tconst file = new File([JSON.stringify(chats, null, '')], fileName, { type: 'application/json' });\n\t\tconst response: { path?: string; message?: string } = <any>await FilePicker.upload(this.DATA_FOLDER, folderPath, file);\n\t\tif (!response.path) {\n\t\t\tconsole.error(`Could not create archive ${fileName}\\nReason: ${response}`);\n\t\t\tthrow new Error('Could not upload the archive to server: ' + fileName);\n\t\t}\n\t\tconst entry: DFChatArchiveEntry = {\n\t\t\tid: id,\n\t\t\tname: name,\n\t\t\tvisible: visible,\n\t\t\tfilepath: response.path,\n\t\t\tfilename: fileName\n\t\t};\n\t\treturn entry;\n\t}\n\n\tstatic async createChatArchive(name: string, chats: ChatMessage[], visible: boolean): Promise<DFChatArchiveEntry> {\n\t\tconst newId = SETTINGS.get<number>(this.PREF_CID) + 1;\n\t\tSETTINGS.set(this.PREF_CID, newId);\n\t\tconst entry = await this._generateChatArchiveFile(newId, name, chats, visible);\n\t\tconst logs = SETTINGS.get<DFChatArchiveEntry[]>(this.PREF_LOGS);\n\t\tlogs.push(entry);\n\t\tawait SETTINGS.set(this.PREF_LOGS, logs);\n\t\tif (this._updateListener != null)\n\t\t\tthis._updateListener();\n\t\treturn entry;\n\t}\n\n\tstatic async getArchiveContents(archive: DFChatArchiveEntry): Promise<(ChatMessage | ChatMessageData)[]> {\n\t\tconst response = await fetch(archive.filepath);\n\t\tconst data = await response.json().catch(error => console.error(`Failed to read JSON for archive ${archive.filepath}\\n${error}`));\n\t\tif (response.ok)\n\t\t\treturn data as (ChatMessage | ChatMessageData)[];\n\t\telse\n\t\t\tthrow new Error('Could not access the archive from server side: ' + archive.filepath);\n\t}\n\n\tstatic async updateChatArchive(archive: DFChatArchiveEntry, newChatData?: (ChatMessage | ChatMessageData)[]): Promise<DFChatArchiveEntry> {\n\t\tif (!this.getLogs().find(x => x.id == archive.id))\n\t\t\tthrow new Error('Could not locate an archive for the given ID: ' + archive.id.toString());\n\t\t// If we are updating the contents of an archive\n\t\tif (newChatData) {\n\t\t\tconst folderPath = SETTINGS.get<string>(this.PREF_FOLDER);\n\t\t\tconst file = new File([JSON.stringify(newChatData)], archive.filename, { type: 'application/json' });\n\t\t\tconst response: {\n\t\t\t\tpath?: string;\n\t\t\t\tmessage?: string;\n\t\t\t} = <any>await FilePicker.upload(this.DATA_FOLDER, folderPath, file, {});\n\t\t\tif (!response.path)\n\t\t\t\tthrow new Error('Could not upload the archive to server side: ' + archive.id.toString());\n\t\t}\n\t\tconst logs = this.getLogs();\n\t\tconst idx = logs.findIndex(x => x.id === archive.id);\n\t\tif (idx < 0) return archive;\n\t\tlogs[idx] = archive;\n\t\tawait SETTINGS.set(DFChatArchive.PREF_LOGS, logs);\n\t\treturn archive;\n\t}\n\n\tstatic async deleteAll() {\n\t\tconst folderPath = SETTINGS.get<string>(this.PREF_FOLDER);\n\t\tconst logs = SETTINGS.get<DFChatArchiveEntry[]>(this.PREF_LOGS);\n\t\t// Can not delete files currently, truncate instead to make filtering easier.\n\t\tawait Promise.all(logs.map(archive => {\n\t\t\tconst file = new File([''], archive.filename, { type: 'application/json' });\n\t\t\treturn FilePicker.upload(this.DATA_FOLDER, folderPath, file, {});\n\t\t}));\n\t\tawait SETTINGS.set(this.PREF_LOGS, []);\n\t\tif (this._updateListener != null)\n\t\t\tthis._updateListener();\n\t}\n\n\tstatic async deleteChatArchive(id: number) {\n\t\tconst folderPath = SETTINGS.get<string>(this.PREF_FOLDER);\n\t\tconst logs = SETTINGS.get<DFChatArchiveEntry[]>(this.PREF_LOGS);\n\t\tconst entryIdx = logs.findIndex(x => x.id === id);\n\t\tif (entryIdx < 0) {\n\t\t\tconsole.error(`Could not find entry for ID#${id}`);\n\t\t\treturn;\n\t\t}\n\t\tconst entry = logs[entryIdx];\n\t\t// Cannot delete file currently, instead truncate the file and move along.\n\t\tconst file = new File([''], entry.filename, { type: 'application/json' });\n\t\tawait FilePicker.upload(this.DATA_FOLDER, folderPath, file, {});\n\t\tlogs.splice(entryIdx, 1);\n\t\tawait SETTINGS.set(this.PREF_LOGS, logs);\n\t\tif (this._updateListener != null)\n\t\t\tthis._updateListener();\n\t}\n}\n","import SETTINGS from \"../../../common/Settings\";\nimport { DFChatArchive } from \"./DFChatArchive\";\nimport DFChatArchiveViewer from \"./DFChatArchiveViewer\";\n\nexport default class DFChatArchiveManager extends Application {\n\tstatic readonly PREF_REVERSE_SORT = 'dfca-manager-reverseSort';\n\tstatic chatViewers: Map<number, DFChatArchiveViewer> = new Map();\n\n\tstatic get defaultOptions() {\n\t\treturn mergeObject(Application.defaultOptions as Partial<ApplicationOptions>, {\n\t\t\ttemplate: \"modules/df-chat-enhance/templates/archive-manager.hbs\",\n\t\t\tresizable: true,\n\t\t\tminimizable: true,\n\t\t\twidth: 300,\n\t\t\theight: 500,\n\t\t\ttitle: \"DF_CHAT_ARCHIVE.ArchiveManager_Title\".localize()\n\t\t}) as ApplicationOptions;\n\t}\n\n\tgetData(options?: any) {\n\t\tconst data = super.getData(options);\n\t\tlet messages = DFChatArchive.getLogs();\n\t\tif (!game.user.isGM)\n\t\t\tmessages = messages.filter(x => x.visible);\n\t\tmessages = messages.sort((a, b) => a.name.localeCompare(b.name));\n\t\tconst reverseSort = SETTINGS.get<boolean>(DFChatArchiveManager.PREF_REVERSE_SORT);\n\t\tmergeObject(data, {\n\t\t\tmessages: reverseSort ? messages.reverse() : messages,\n\t\t\tisGM: game.user.isGM,\n\t\t\treverseSort\n\t\t});\n\t\treturn data;\n\t}\n\n\tprivate _subscribeView(element: JQuery) {\n\t\telement.on('click', function () {\n\t\t\tconst id = parseInt($(this).attr('data-id'));\n\t\t\tif (isNaN(id) || !DFChatArchive.exists(id)) {\n\t\t\t\tui.notifications.error('DF_CHAT_ARCHIVE.ArchiveManager_ErrorBadId'.localize());\n\t\t\t\tthrow Error(`Invalid id for Chat Archive: '${$(this).attr('data-id')}'`);\n\t\t\t}\n\t\t\tif (DFChatArchiveManager.chatViewers.has(id)) {\n\t\t\t\tDFChatArchiveManager.chatViewers.get(id).bringToTop();\n\t\t\t} else {\n\t\t\t\tDFChatArchiveManager.chatViewers.set(id, new DFChatArchiveViewer(DFChatArchive.getArchive(id), view => {\n\t\t\t\t\tDFChatArchiveManager.chatViewers.delete(view.archive.id);\n\t\t\t\t}));\n\t\t\t\tDFChatArchiveManager.chatViewers.get(id).render(true);\n\t\t\t}\n\t\t});\n\t}\n\tprivate _subscribeDelete(element: JQuery) {\n\t\telement.on('click', async function () {\n\t\t\tconst id = parseInt($(this).attr('data-id'));\n\t\t\tif (isNaN(id) || !DFChatArchive.exists(id)) {\n\t\t\t\tui.notifications.error('DF_CHAT_ARCHIVE.ArchiveManager_ErrorBadId'.localize());\n\t\t\t\tthrow Error(`Invalid id for Chat Archive: '${$(this).attr('data-id')}'`);\n\t\t\t}\n\t\t\tconst archive = DFChatArchive.getArchive(id);\n\t\t\tawait Dialog.confirm({\n\t\t\t\ttitle: 'DF_CHAT_ARCHIVE.ArchiveManager_ConfirmDeleteArchiveTitle'.localize(),\n\t\t\t\tcontent: 'DF_CHAT_ARCHIVE.ArchiveManager_ConfirmDeleteArchiveContent'.localize().replace('{name}', archive.name),\n\t\t\t\tdefaultYes: false,\n\t\t\t\tyes: async () => await DFChatArchive.deleteChatArchive(id)\n\t\t\t});\n\t\t});\n\t}\n\n\tactivateListeners(html: JQuery) {\n\t\tDFChatArchive.setUpdateListener(this._archiveChanged.bind(this));\n\t\tif (DFChatArchive.getLogs().length > 0)\n\t\t\thtml.find('p.dfca-no-items').hide();\n\t\thtml.find('a[data-type=\"view\"]').each((i, element) => { this._subscribeView($(element)); });\n\t\thtml.find('a[data-type=\"delete\"]').each((i, element) => { this._subscribeDelete($(element)); });\n\t\thtml.find('#dfca-delete-all').on('click', async function () {\n\t\t\tawait Dialog.confirm({\n\t\t\t\ttitle: 'DF_CHAT_ARCHIVE.ArchiveManager_ConfirmDeleteAllTitle'.localize(),\n\t\t\t\tcontent: 'DF_CHAT_ARCHIVE.ArchiveManager_ConfirmDeleteAllMessage1'.localize(),\n\t\t\t\tdefaultYes: false,\n\t\t\t\tyes: async () => {\n\t\t\t\t\tawait Dialog.confirm({\n\t\t\t\t\t\ttitle: 'DF_CHAT_ARCHIVE.ArchiveManager_ConfirmDeleteAllTitle'.localize(),\n\t\t\t\t\t\tcontent: 'DF_CHAT_ARCHIVE.ArchiveManager_ConfirmDeleteAllMessage2'.localize(),\n\t\t\t\t\t\tdefaultYes: false,\n\t\t\t\t\t\tyes: async () => {\n\t\t\t\t\t\t\tawait DFChatArchive.deleteAll();\n\t\t\t\t\t\t\tui.notifications.info('DF_CHAT_ARCHIVE.ArchiveManager_ConfirmDeleteAllComplete'.localize());\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\tconst asc = html.find('#dfca-sort-asc');\n\t\tconst dsc = html.find('#dfca-sort-dsc');\n\t\tasc.on('click', async () => {\n\t\t\tawait SETTINGS.set(DFChatArchiveManager.PREF_REVERSE_SORT, true);\n\t\t\tasc.hide();\n\t\t\tdsc.show();\n\t\t\tthis.render();\n\t\t});\n\t\tdsc.on('click', async () => {\n\t\t\tawait SETTINGS.set(DFChatArchiveManager.PREF_REVERSE_SORT, false);\n\t\t\tdsc.hide();\n\t\t\tasc.show();\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tclose(options?: any): Promise<void> {\n\t\tDFChatArchive.setUpdateListener(null);\n\t\treturn super.close(options);\n\t}\n\n\tprivate async _archiveChanged() {\n\t\tlet logs = DFChatArchive.getLogs();\n\t\tif (!game.user.isGM)\n\t\t\tlogs = logs.filter(x => x.visible);\n\t\tconst archiveContainer = this.element.find('#dfca-archives');\n\t\tarchiveContainer.empty();\n\t\t// Add new items\n\t\tfor (const archive of logs) {\n\t\t\tconst visible = archive.visible === true\n\t\t\t\t? `<i class=\"dfca-visible fas fa-users\" title=\"${'DF_CHAT_ARCHIVE.ArchiveManager_VisibleToPlayers'.localize()}\"></i>` : '';\n\t\t\tconst html = $(`\n\t\t<li class=\"dfca-archive-item\" data-id=\"${archive.id}\">\n\t\t\t<div>\n\t\t\t\t<a class=\"button dfca-view\" data-type=\"view\" data-id=\"${archive.id}\"><i class=\"fas fa-eye\"></i>\n\t\t\t\t\t<span>${archive.name}</span>\n\t\t\t\t</a>\n\t\t\t\t${visible}\n\t\t\t\t<a class=\"button dfca-delete\" data-type=\"delete\" data-id=\"${archive.id}\"><i class=\"fas fa-trash\"></i></a>\n\t\t\t</div>\n\t\t</li>`);\n\t\t\tthis._subscribeView(html.find('a[data-type=\"view\"]'));\n\t\t\tthis._subscribeDelete(html.find('a[data-type=\"delete\"]'));\n\t\t\tarchiveContainer.append(html);\n\t\t}\n\t\tif (archiveContainer[0].children.length == 0)\n\t\t\tthis.element.find('p.dfca-no-items').show();\n\t\telse\n\t\t\tthis.element.find('p.dfca-no-items').hide();\n\t}\n}","import { DFChatArchive } from \"./DFChatArchive\";\nimport SETTINGS from \"../../../common/Settings\";\n\nexport default class DFChatArchiveNew extends FormApplication<FormApplicationOptions, { shouldDelete: boolean }> {\n\tstatic readonly PREF_DELETE = 'new-should-delete';\n\tstatic readonly PREF_HIDE_EXPORT = 'hide-export';\n\tstatic get defaultOptions() {\n\t\treturn mergeObject(FormApplication.defaultOptions, {\n\t\t\ttemplate: \"modules/df-chat-enhance/templates/archive-new.hbs\",\n\t\t\tresizable: false,\n\t\t\tminimizable: false,\n\t\t\ttitle: \"DF_CHAT_ARCHIVE.ArchiveNew_Title\".localize()\n\t\t});\n\t}\n\n\tstatic registerSettings() {\n\t\tSETTINGS.register(DFChatArchiveNew.PREF_DELETE, {\n\t\t\tconfig: false,\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tdefault: true\n\t\t});\n\t}\n\n\tgetData(options?: any) {\n\t\treturn mergeObject(super.getData(options), {\n\t\t\tshouldDelete: SETTINGS.get(DFChatArchiveNew.PREF_DELETE) as boolean\n\t\t});\n\t}\n\n\tasync _updateObject(_event?: any, formData?: any) {\n\t\tSETTINGS.set(DFChatArchiveNew.PREF_DELETE, formData.delete);\n\n\t\tconst name = formData.name;\n\t\tif (!name) {\n\t\t\tui.notifications.warn('DF_CHAT_ARCHIVE.ArchiveNew_ErrorNameMissing'.localize());\n\t\t\tthrow Error('DF_CHAT_ARCHIVE.ArchiveNew_ErrorNameMissing'.localize());\n\t\t}\n\n\t\tlet chats = <ChatMessage[]>[...(ui.chat.collection.values())];\n\n\t\t// If we are selecting a date range\n\t\tif (formData['date-or-all'] === 'date') {\n\t\t\tconst fromDate = new Date(formData.from).getTime();\n\t\t\tconst toDate = new Date(formData.to).getTime();\n\t\t\tif (isNaN(fromDate) || isNaN(toDate)) {\n\t\t\t\tui.notifications.warn('DF_CHAT_ARCHIVE.ArchiveNew_ErrorDatesMissing'.localize());\n\t\t\t\tthrow Error('Missing \"from\" and/or \"to\" dates');\n\t\t\t}\n\t\t\tchats = chats.filter((value) => value.data.timestamp >= fromDate && value.data.timestamp <= toDate);\n\t\t}\n\n\t\tui.notifications.info('DF_CHAT_ARCHIVE.ArchiveNew_NoticeSuccess'.localize().replace('{0}', name));\n\t\ttry {\n\t\t\tawait DFChatArchive.createChatArchive(name, chats, formData['visible']);\n\t\t}\n\t\tcatch (e) {\n\t\t\t// We have failed to create an archive so we should return immediately\n\t\t\treturn;\n\t\t}\n\t\t// If we don't want to delete the messages, return\n\t\tif (!formData.delete) return;\n\n\t\tgame.messages.flush();\n\t}\n\n\t_renderInner(data: { shouldDelete: boolean }): Promise<JQuery<HTMLElement>> {\n\t\treturn super._renderInner(data)\n\t\t\t.then((html) => {\n\t\t\t\tconst from = html.find('#dfca-from');\n\t\t\t\tconst to = html.find('#dfca-to');\n\t\t\t\thtml.find('#dfca-all').on('change', () => {\n\t\t\t\t\tfrom.prop('disabled', true);\n\t\t\t\t\tto.prop('disabled', true);\n\t\t\t\t\tthis._recalculateDimensions();\n\t\t\t\t});\n\t\t\t\thtml.find('#dfca-date').on('change', () => {\n\t\t\t\t\tfrom.prop('disabled', false);\n\t\t\t\t\tto.prop('disabled', false);\n\t\t\t\t\tthis._recalculateDimensions();\n\t\t\t\t});\n\t\t\t\treturn html;\n\t\t\t});\n\t}\n}","import { ChatMessageData } from '@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs';\nimport { DFChatArchive, DFChatArchiveEntry } from './DFChatArchive';\n\nexport default class DFChatArchiveViewer extends Application {\n\tarchive: DFChatArchiveEntry;\n\tmessages: ChatMessageData[];\n\tonCloseCallBack: (view: DFChatArchiveViewer) => void;\n\tconstructor(archive: DFChatArchiveEntry, onCloseCallBack: (view: DFChatArchiveViewer) => void) {\n\t\tsuper();\n\t\tthis.archive = archive;\n\t\tthis.onCloseCallBack = onCloseCallBack;\n\t}\n\n\tstatic get defaultOptions() {\n\t\treturn mergeObject(Application.defaultOptions as Partial<ApplicationOptions>, {\n\t\t\ttemplate: \"modules/df-chat-enhance/templates/archive-viewer.hbs\",\n\t\t\twidth: 300,\n\t\t\theight: 500,\n\t\t\tresizable: true,\n\t\t\ttitle: 'DF_CHAT_ARCHIVE.ArchiveViewer_Title',\n\t\t\tclasses: ['df-chat-log-window']\n\t\t}) as ApplicationOptions;\n\t}\n\n\tgetData(options = {}) {\n\t\tsuper.getData(options);\n\t\treturn {\n\t\t\tname: this.archive.name,\n\t\t\tisGM: game.user.isGM,\n\t\t\tvisible: this.archive.visible ?? false,\n\t\t\tlogId: 'df-chat-log-' + this.archive.id\n\t\t};\n\t}\n\n\t// convert a Unicode string to a string in which\n\t// each 16-bit unit occupies only one byte\n\t/**\n\t * Converts a UTF-16 string to an ASCii string containing the binary data of the UTF-16 text.\n\t * @param data UTF-16 data\n\t * @returns Binary data coerced into a string\n\t */\n\tprivate static toBinary(data: string): string {\n\t\tconst codeUnits = new Uint16Array(data.length);\n\t\tfor (let i = 0; i < codeUnits.length; i++) {\n\t\t\tcodeUnits[i] = data.charCodeAt(i);\n\t\t}\n\t\tconst charCodes = new Uint8Array(codeUnits.buffer);\n\t\tlet result = '';\n\t\tfor (let i = 0; i < charCodes.byteLength; i++) {\n\t\t\tresult += String.fromCharCode(charCodes[i]);\n\t\t}\n\t\treturn result;\n\t}\n\n\t_renderInner(data: any): Promise<JQuery> {\n\t\treturn (super._renderInner(data) as Promise<JQuery>)\n\t\t\t.then(async (html: JQuery<HTMLElement>) => {\n\t\t\t\thtml.find(\"#visible-df-chat-log-\" + this.archive.id).on('change', async (element) => {\n\t\t\t\t\tthis.archive.visible = (element.target as HTMLInputElement).checked;\n\t\t\t\t\tawait DFChatArchive.updateChatArchive(this.archive);\n\t\t\t\t});\n\t\t\t\thtml.find(\"#edit\").on('click', async () => {\n\t\t\t\t\tsetTimeout(async () => {\n\t\t\t\t\t\tconst dialog = new Dialog({\n\t\t\t\t\t\t\ttitle: \"DF_CHAT_ARCHIVE.ArchiveViewer_NameEdit_Title\".localize(),\n\t\t\t\t\t\t\tcontent: `<input id=\"name\" type=\"text\" value=\"${this.archive.name}\"/>`,\n\t\t\t\t\t\t\tbuttons: {\n\t\t\t\t\t\t\t\tsave: {\n\t\t\t\t\t\t\t\t\ticon: '<i class=\"fas fa-save\"></i>',\n\t\t\t\t\t\t\t\t\tlabel: 'DF_CHAT_ARCHIVE.ArchiveViewer_NameEdit_Save'.localize(),\n\t\t\t\t\t\t\t\t\tcallback: async (html) => {\n\t\t\t\t\t\t\t\t\t\tthis.archive.name = $(html).find('#name').val() as string;\n\t\t\t\t\t\t\t\t\t\tawait dialog.close();\n\t\t\t\t\t\t\t\t\t\tawait DFChatArchive.updateChatArchive(this.archive);\n\t\t\t\t\t\t\t\t\t\tawait this.render(false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tclose: {\n\t\t\t\t\t\t\t\t\ticon: '<i class=\"fas fa-times\"></i>',\n\t\t\t\t\t\t\t\t\tlabel: 'DF_CHAT_ARCHIVE.ArchiveViewer_NameEdit_Cancel'.localize(),\n\t\t\t\t\t\t\t\t\tcallback: async () => {\n\t\t\t\t\t\t\t\t\t\tawait dialog.close();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdefault: 'save'\n\t\t\t\t\t\t});\n\t\t\t\t\t\tdialog.render(true);\n\t\t\t\t\t}, 1);\n\t\t\t\t});\n\t\t\t\thtml.find('#print').on('click', async () => {\n\t\t\t\t\tconst clone = html.find('#df-chat-log').clone();\n\t\t\t\t\tclone.addClass('df-chat-print');\n\t\t\t\t\t$('body').hide();\n\t\t\t\t\t$('html').addClass('df-chat-print');\n\t\t\t\t\t$('html').append(clone);\n\t\t\t\t\twindow.print();\n\t\t\t\t\tclone.remove();\n\t\t\t\t\t$('html').removeClass('df-chat-print');\n\t\t\t\t\t$('body').show();\n\t\t\t\t});\n\t\t\t\thtml.find('#merge').on('click', async () => {\n\t\t\t\t\tif (DFChatArchive.getLogs().length == 1) {\n\t\t\t\t\t\tui.notifications.info('DF_CHAT_ARCHIVE.ArchiveViewer_Merge_OnlyOneArchive'.localize());\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst dialog: Dialog = new Dialog({\n\t\t\t\t\t\ttitle: 'DF_CHAT_ARCHIVE.ArchiveViewer_Merge_Title'.localize(),\n\t\t\t\t\t\tdefault: 'merge',\n\t\t\t\t\t\tcontent: await renderTemplate('modules/df-chat-enhance/templates/archive-merge.hbs', {\n\t\t\t\t\t\t\tid: this.archive.id,\n\t\t\t\t\t\t\tname: this.archive.name,\n\t\t\t\t\t\t\tarchives: DFChatArchive.getLogs().filter(x => x.id != this.archive.id)\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tbuttons: {\n\t\t\t\t\t\t\tcancel: {\n\t\t\t\t\t\t\t\ticon: '<i class=\"fas fa-times\"></i>',\n\t\t\t\t\t\t\t\tlabel: 'DF_CHAT_ARCHIVE.ArchiveViewer_Merge_Cancel'.localize(),\n\t\t\t\t\t\t\t\tcallback: async () => await dialog.close()\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmerge: {\n\t\t\t\t\t\t\t\ticon: '<i class=\"fas fa-sitemap\"></i>',\n\t\t\t\t\t\t\t\tlabel: 'DF_CHAT_ARCHIVE.ArchiveViewer_Merge_Merge'.localize(),\n\t\t\t\t\t\t\t\tcallback: async (html) => {\n\t\t\t\t\t\t\t\t\tconst val = $(html).find('#archive').val() as string;\n\t\t\t\t\t\t\t\t\tif (isNaN(parseInt(val))) return;\n\t\t\t\t\t\t\t\t\tconst id = parseInt(val);\n\t\t\t\t\t\t\t\t\tconst source = DFChatArchive.getLogs().find(x => x.id == id);\n\t\t\t\t\t\t\t\t\tconst currentChats = await DFChatArchive.getArchiveContents(this.archive);\n\t\t\t\t\t\t\t\t\tconst sourceChats = await DFChatArchive.getArchiveContents(source);\n\t\t\t\t\t\t\t\t\tconst mergedChats = (currentChats as ChatMessageData[])\n\t\t\t\t\t\t\t\t\t\t.concat(sourceChats as ChatMessageData[])\n\t\t\t\t\t\t\t\t\t\t.sort((a, b) => a.timestamp - b.timestamp);\n\t\t\t\t\t\t\t\t\tawait DFChatArchive.updateChatArchive(this.archive, mergedChats);\n\t\t\t\t\t\t\t\t\tthis.render(true);\n\t\t\t\t\t\t\t\t\tif (($(html).find('#delete-' + this.archive.id)[0] as HTMLInputElement).checked) {\n\t\t\t\t\t\t\t\t\t\tawait DFChatArchive.deleteChatArchive(id);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tawait dialog.render(true);\n\t\t\t\t});\n\n\t\t\t\thtml.find('#html').on('click', () => {\n\t\t\t\t\tconst data = $('<div></div>').append(html.find('#df-chat-log').clone()).html();\n\t\t\t\t\tconst anchor = document.createElement('a');\n\t\t\t\t\tanchor.download = encodeURI(this.archive.name) + '.html';\n\t\t\t\t\t// anchor.href = \"data:text/html;base64,\" + btoa(unescape(encodeURIComponent(data)));\n\t\t\t\t\tanchor.href = \"data:text/html,\" + encodeURIComponent(data);\n\t\t\t\t\tanchor.click();\n\t\t\t\t});\n\n\t\t\t\tconst log = html.find('#df-chat-log');\n\t\t\t\tconst messageHtml = [];\n\t\t\t\tthis.messages = (await DFChatArchive.getArchiveContents(this.archive) as ChatMessageData[])\n\t\t\t\t\t.filter(x => game.user.isGM || x.user === game.userId || x.type !== CONST.CHAT_MESSAGE_TYPES.WHISPER || x.whisper.some(x => x === game.userId));\n\n\t\t\t\tconst deletionList: string[] = [];\n\t\t\t\tconst deleteButton = html.find('#dfal-save-changes');\n\t\t\t\tfor (const value of this.messages as ChatMessageData[]) {\n\t\t\t\t\tconst chatMessage = value instanceof ChatMessage ? value : new ChatMessage(value);\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// @ts-ignore\n\t\t\t\t\t\tconst html = await chatMessage.getHTML();\n\t\t\t\t\t\t// if we only have 1 message, don't allow it to be deleted. They might as well just delete the archive\n\t\t\t\t\t\tif (this.messages.length == 1)\n\t\t\t\t\t\t\thtml.find('a.message-delete').hide();\n\t\t\t\t\t\thtml.find('a.message-delete').on('click', (event: JQuery.ClickEvent) => {\n\t\t\t\t\t\t\tconst messageHtml = $(event.target.parentElement?.parentElement?.parentElement?.parentElement);\n\t\t\t\t\t\t\tconst buttonIcon = $(event.target);\n\t\t\t\t\t\t\tif (messageHtml.hasClass('dfal-deleted')) {\n\t\t\t\t\t\t\t\tmessageHtml.removeClass('dfal-deleted');\n\t\t\t\t\t\t\t\tbuttonIcon.removeClass('fa-redo-alt');\n\t\t\t\t\t\t\t\tbuttonIcon.addClass('fa-trash');\n\t\t\t\t\t\t\t\tdeletionList.splice(deletionList.findIndex(x => x === messageHtml.attr('data-message-id')), 1);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tmessageHtml.addClass('dfal-deleted');\n\t\t\t\t\t\t\t\tbuttonIcon.removeClass('fa-trash');\n\t\t\t\t\t\t\t\tbuttonIcon.addClass('fa-redo-alt');\n\t\t\t\t\t\t\t\tdeletionList.push(messageHtml.attr('data-message-id'));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (deletionList.length > 0) deleteButton.show();\n\t\t\t\t\t\t\telse deleteButton.hide();\n\t\t\t\t\t\t});\n\t\t\t\t\t\tmessageHtml.push(html);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(`Chat message ${chatMessage.id} failed to render.\\n${err})`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Prepend the HTML\n\t\t\t\tlog.prepend(messageHtml);\n\n\t\t\t\tdeleteButton.hide();\n\t\t\t\tdeleteButton.on('click', async () => {\n\t\t\t\t\tif (deletionList.length === this.messages.length) {\n\t\t\t\t\t\tui.notifications.warn('DF_CHAT_ARCHIVE.ArchiveViewer_Error_Delete_All'.localize());\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tDialog.confirm({\n\t\t\t\t\t\ttitle: \"DF_CHAT_ARCHIVE.ArchiveViewer_DeleteTitle\".localize(),\n\t\t\t\t\t\tcontent: \"DF_CHAT_ARCHIVE.ArchiveViewer_DeleteContent\".localize(),\n\t\t\t\t\t\tdefaultYes: false,\n\t\t\t\t\t\tyes: async () => {\n\t\t\t\t\t\t\tfor (const id of deletionList) {\n\t\t\t\t\t\t\t\tconst message = html.find(`li[data-message-id=\"${id}\"]`);\n\t\t\t\t\t\t\t\tmessage.hide(500, () => message.remove());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis.messages = this.messages.filter((x: any) => !deletionList.includes(x._id));\n\t\t\t\t\t\t\tawait DFChatArchive.updateChatArchive(this.archive, this.messages);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\treturn html;\n\t\t\t});\n\t}\n\tclose(options?: Application.CloseOptions): Promise<void> {\n\t\tthis.onCloseCallBack(this);\n\t\treturn super.close(options);\n\t}\n}","import DFChatArchiveNew from \"./DFChatArchiveNew\";\nimport DFChatArchiveManager from \"./DFChatArchiveManager\";\nimport { DFChatArchive } from \"./DFChatArchive\";\nimport SETTINGS from \"../../../common/Settings\";\n\n\nexport function init() {\n\n\tlet archiveNew: DFChatArchiveNew = null;\n\tlet archiveManager: DFChatArchiveManager = null;\n\n\tDFChatArchive.registerSettings();\n\tDFChatArchiveNew.registerSettings();\n\n\tSETTINGS.register(DFChatArchiveNew.PREF_HIDE_EXPORT, {\n\t\tname: 'DF_CHAT_ARCHIVE.Settings.HideExport',\n\t\tscope: 'world',\n\t\ttype: Boolean,\n\t\tdefault: false,\n\t\tconfig: true,\n\t\tonChange: (newValue) => {\n\t\t\tif (!newValue)\n\t\t\t\t$('#chat-controls .export-log').show();\n\t\t\telse\n\t\t\t\t$('#chat-controls .export-log').hide();\n\t\t}\n\t});\n\n\tSETTINGS.register(DFChatArchiveManager.PREF_REVERSE_SORT, {\n\t\tscope: 'world',\n\t\ttype: Boolean,\n\t\tdefault: false,\n\t\tconfig: false\n\t});\n\n\tHooks.on('renderChatLog', function (chatLog: ChatLog, html: JQuery<HTMLElement>) {\n\t\tconst archiveButton = $(`<a class=\"button chat-archive\" title=\"${'DF_CHAT_ARCHIVE.ExportButtonTitle'.localize()}\">\n\t\t<i class=\"fas fa-archive\"></i></a>`);\n\t\tarchiveButton.on('click', () => {\n\t\t\tif (archiveNew == null) {\n\t\t\t\tarchiveNew = new DFChatArchiveNew({});\n\t\t\t\tarchiveNew.render(true);\n\t\t\t} else {\n\t\t\t\tarchiveNew.bringToTop();\n\t\t\t}\n\t\t});\n\t\thtml.find('.control-buttons')\n\t\t\t.prepend(archiveButton)\n\t\t\t.attr('style', 'flex:0 0 auto;');\n\t\tif (SETTINGS.get(DFChatArchiveNew.PREF_HIDE_EXPORT)) {\n\t\t\thtml.find('.control-buttons .export-log').hide();\n\t\t}\n\t});\n\n\tHooks.on('renderSettings', function (settings: Settings, html: JQuery<HTMLElement>) {\n\t\tconst archiveManagerHtml = $(`<div id=\"df-chat-enhance-settings\" style=\"margin:0\">\n\t<h4>${'DF_CHAT_ARCHIVE.ChatEnhanceSettingGroup'.localize()}</h4>\n\t<button data-action=\"archive\"><i class=\"fas fa-archive\"></i>${'DF_CHAT_ARCHIVE.OpenChatArchive'.localize()}</button>\n</div>`);\n\t\tarchiveManagerHtml.on('click', () => {\n\t\t\tif (archiveManager == null || ![Application.RENDER_STATES.RENDERED, Application.RENDER_STATES.RENDERING].includes((<any>archiveManager)._state)) {\n\t\t\t\tarchiveManager = new DFChatArchiveManager();\n\t\t\t\tarchiveManager.render(true);\n\t\t\t} else {\n\t\t\t\tarchiveManager.bringToTop();\n\t\t\t}\n\t\t});\n\t\thtml.find('#settings-game').append(archiveManagerHtml);\n\t});\n\tHooks.on('closeDFChatArchiveNew', () => { archiveNew = null; });\n\tHooks.on('closeDFChatArchiveManager', () => { archiveNew = null; });\n\tHooks.on(`renderDFChatArchiveNew`, function (app: any, html: JQuery) {\n\t\thtml.find('input[type=\"text\"]')[0].focus();\n\t});\n}\n","import { ChatMessageData } from \"@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs\";\nimport SETTINGS from \"../../../common/Settings\";\nimport UTIL from \"../Util\";\n\nexport default class ChatTime {\n\n\tprivate static readonly PREF_ENABLED = 'ChatTime.UseSimpleCalender';\n\tprivate static readonly PREF_FORMAT = 'ChatTime.SimpleCalendarFormat';\n\tprivate static readonly FLAG_CHAT_TIME = 'ChatTime.WorldTime';\n\n\tprivate static get enabled() { return SETTINGS.get(this.PREF_ENABLED); }\n\tprivate static get simpleCalendarActive() { return !!game.modules.get('foundryvtt-simple-calendar')?.active; }\n\n\tstatic ready() {\n\t\tif (!this.simpleCalendarActive && game.user.isGM && this.enabled)\n\t\t\tui.notifications.warn('DF_CHAT_TIME.ErrorSimpleCalendarMissing', { permanent: true, localize: true });\n\t}\n\n\tstatic init() {\n\t\tSETTINGS.register(this.PREF_ENABLED, {\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tname: \"DF_CHAT_TIME.EnabledName\",\n\t\t\thint: \"DF_CHAT_TIME.EnabledHint\",\n\t\t\tdefault: false,\n\t\t\tconfig: true,\n\t\t\tonChange: UTIL.reloadChatLog\n\t\t});\n\n\t\tSETTINGS.register(this.PREF_FORMAT, {\n\t\t\tscope: 'world',\n\t\t\ttype: String,\n\t\t\tname: 'DF_CHAT_TIME.FormatName',\n\t\t\thint: 'DF_CHAT_TIME.FormatHint',\n\t\t\tdefault: 'YYYY, MMM DD, HH:mm',\n\t\t\tconfig: this.simpleCalendarActive,\n\t\t\tonChange: UTIL.reloadChatLog\n\t\t});\n\n\t\tlibWrapper.register(SETTINGS.MOD_NAME, 'ChatMessage.implementation.create',\n\t\t\t(wrapped: (...args: any) => unknown, chatData: Partial<ChatMessageData>, createOptions: any) => {\n\t\t\t\tchatData.flags = chatData.flags ?? {};\n\t\t\t\tchatData.flags[SETTINGS.MOD_NAME] = {};\n\t\t\t\t(chatData.flags[SETTINGS.MOD_NAME] as any)[this.FLAG_CHAT_TIME] = game.time.worldTime;\n\t\t\t\treturn wrapped(chatData, createOptions);\n\t\t\t}, 'WRAPPER');\n\n\t\tHooks.on('renderChatMessage', (message: ChatMessage, html: JQuery<HTMLElement>, _data: any) => {\n\t\t\tif (!this.simpleCalendarActive || !this.enabled) return;\n\t\t\tconst simpleTimestamp = <number>message.getFlag(SETTINGS.MOD_NAME, this.FLAG_CHAT_TIME);\n\t\t\tif (simpleTimestamp === undefined) return;\n\t\t\tconst timeElement = html.find('.message-timestamp');\n\t\t\tconst simpleTimeElement = $(`<time class=\"dfce-simple-timestamp\">${SimpleCalendar.api.formatDateTime(\n\t\t\t\tSimpleCalendar.api.timestampToDate(simpleTimestamp), SETTINGS.get<string>(this.PREF_FORMAT)\n\t\t\t)}</time>`);\n\t\t\ttimeElement.after(simpleTimeElement);\n\t\t\ttimeElement.hide();\n\t\t});\n\t}\n}","import { ChatMessageData } from \"@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs\";\nimport SETTINGS from \"../../../common/Settings\";\nimport DFChatEdit from \"./df-chat-edit\";\n\n\ndeclare namespace marked {\n\tfunction parse(md: string, options: any): string;\n}\n\nexport default class DFChatEditor extends FormApplication {\n\tprivate chatMessage: ChatMessageData & ChatMessage;\n\tpublic static readonly PREF_MARKDOWN = 'edit-markdown';\n\n\t/**\n\t * Assign the default options which are supported by the entity edit sheet.\n\t * @returns The default options for this FormApplication class\n\t * @override\n\t * @see {@link Application.defaultOptions}\n\t */\n\tstatic get defaultOptions(): FormApplicationOptions {\n\t\treturn mergeObject(FormApplication.defaultOptions as Partial<FormApplicationOptions>, {\n\t\t\tcloseOnSubmit: true,\n\t\t\teditable: true,\n\t\t\tresizable: true,\n\t\t\twidth: 400,\n\t\t\tpopOut: true,\n\t\t\ttitle: 'DF_CHAT_EDIT.Editor_Title',\n\t\t\ttemplate: 'modules/df-chat-enhance/templates/chat-edit.hbs'\n\t\t}) as FormApplicationOptions;\n\t}\n\n\tconstructor(chatMessage: ChatMessageData & ChatMessage) {\n\t\tsuper({});\n\t\tthis.chatMessage = chatMessage;\n\t}\n\n\t/** @override */\n\tgetData(options?: any): any {\n\n\t\t// Collect the different Actor types and the labels for those types\n\t\tconst types = Object.keys(CONFIG.Actor.typeLabels).map(type => {\n\t\t\treturn { type, label: CONFIG.Actor.typeLabels[type], actors: [] };\n\t\t});\n\t\t// Organize the actors in the current scene into those type categories\n\t\tfor (const type of types) {\n\t\t\ttype.actors = game.scenes.viewed.tokens.contents.filter(x => x.actor.type === type.type).map(x => ({\n\t\t\t\tid: 'token-' + x.id,\n\t\t\t\tname: x.name\n\t\t\t}));\n\t\t}\n\n\t\tlet selected = '';\n\t\tif (this.chatMessage.user)\n\t\t\tselected = 'user-' + this.chatMessage.user;\n\t\tif (this.chatMessage.speaker.token)\n\t\t\tselected = 'token-' + this.chatMessage.speaker.token;\n\n\t\treturn mergeObject(options, {\n\t\t\tselected,\n\t\t\tplayers: game.users.map(x => ({ id: 'user-' + x.id, name: x.name })),\n\t\t\tactorGroups: types.filter(x => x.actors.length > 0),\n\t\t\tmessageText: this.chatMessage.content\n\t\t\t\t.replace(/< *br *\\/?>/gm, '\\n')\n\t\t\t\t.replace(/<p +class=\"df-edited\">.+/, '')\n\t\t});\n\t}\n\n\t/** @override */\n\tactivateListeners(html: JQuery): void {\n\t\tsuper.activateListeners(html);\n\t\thtml.find('#cancel').on('click', async () => await this.close());\n\t}\n\n\t/** @override */\n\tasync _updateObject(_event?: any, formData?: { content: string, speaker: string }) {\n\t\tlet data = formData.content as string;\n\t\tif (SETTINGS.get(DFChatEditor.PREF_MARKDOWN)) {\n\t\t\tdata = DFChatEditor.processMarkdown(data)[1];\n\t\t} else {\n\t\t\tdata = data.replace(/\\r?\\n/gm, '<br/>');\n\t\t}\n\t\tif (SETTINGS.get<boolean>(DFChatEdit.PREF_SHOW_EDITED) && data.search(/<p +class=\"df-edited\">/) < 0) {\n\t\t\tdata += `<p class=\"df-edited\">${'DF_CHAT_EDIT.EditedFlag'.localize()}</p>`;\n\t\t}\n\n\t\tlet speaker = undefined;\n\t\tlet user = undefined;\n\t\tif (formData.speaker.startsWith('user-')) {\n\t\t\tuser = game.users.get(formData.speaker.substring('user-'.length)).id;\n\t\t\t// @ts-expect-error\n\t\t\tspeaker = ChatMessage._getSpeakerFromUser({ user });\n\t\t} else\n\t\t\tspeaker = ChatMessage.getSpeaker({ token: game.scenes.viewed.tokens.get(formData.speaker.substring('token-'.length)) });\n\t\tif (speaker.alias === undefined)\n\t\t\tspeaker.alias = null;\n\t\tthis.chatMessage.update({ content: data, speaker, user });\n\t}\n\t/** @override */\n\tclose(options?: FormApplication.CloseOptions) {\n\t\tdelete (<any>this.chatMessage).chatEditor;\n\t\treturn super.close(options);\n\t}\n\n\tpublic static processMarkdown(message: string) {\n\t\tconst originalMessage = message;\n\t\tmessage = marked.parse(message, {\n\t\t\theaderIds: false,\n\t\t\tbreaks: true\n\t\t}).trimEnd();\n\t\tif (message.startsWith('<p>'))\n\t\t\tmessage = message.substr(3);\n\t\tif (message.endsWith('</p>'))\n\t\t\tmessage = message.substr(0, message.length - 4);\n\t\tconst newLine = /(<\\/?[ a-z]+>)\\n(<\\/?[ a-z]+>?)/;\n\t\twhile (newLine.test(message))\n\t\t\tmessage = message.replace(newLine, '$1$2');\n\t\treturn [originalMessage, message];\n\t}\n}","import { ChatMessageData } from \"@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs\";\nimport SETTINGS from \"../../../common/Settings\";\nimport DFChatEditor from './DFChatEditor';\n\nconst PREF_EDIT_ALLOWED = 'edit-allowed';\nconst PREF_GM_ALL = 'gm-edit-all';\nconst PREF_IGNORE_HTML = 'edit-ignore-html';\n\nexport default class DFChatEdit {\n\tstatic readonly PREF_SHOW_EDITED = 'DFChatEdit.ShowEditedLable';\n\n\tstatic ready() {\n\t\tSETTINGS.register(DFChatEditor.PREF_MARKDOWN, {\n\t\t\tname: 'DF_CHAT_EDIT.Settings_MarkdownName',\n\t\t\thint: 'DF_CHAT_EDIT.Settings_MarkdownHint',\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tconfig: true,\n\t\t\tscope: 'world'\n\t\t});\n\t\tSETTINGS.register(PREF_EDIT_ALLOWED, {\n\t\t\tname: 'DF_CHAT_EDIT.Settings_AllowEditName',\n\t\t\thint: 'DF_CHAT_EDIT.Settings_AllowEditHint',\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tscope: 'world',\n\t\t\tconfig: true\n\t\t});\n\t\tSETTINGS.register(PREF_GM_ALL, {\n\t\t\tname: 'DF_CHAT_EDIT.Settings_GMEditAllName',\n\t\t\thint: 'DF_CHAT_EDIT.Settings_GMEditAllHint',\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t\tconfig: true,\n\t\t\tscope: 'world'\n\t\t});\n\t\tSETTINGS.register(PREF_IGNORE_HTML, {\n\t\t\tname: 'DF_CHAT_EDIT.Settings_IgnoreHtmlName',\n\t\t\thint: 'DF_CHAT_EDIT.Settings_IgnoreHtmlHint',\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t\tconfig: true,\n\t\t\tscope: 'world'\n\t\t});\n\t\tSETTINGS.register(this.PREF_SHOW_EDITED, {\n\t\t\tname: 'DF_CHAT_EDIT.Settings_ShowEditedLabelName',\n\t\t\thint: 'DF_CHAT_EDIT.Settings_ShowEditedLabelHint',\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tconfig: true,\n\t\t\tscope: 'world'\n\t\t});\n\n\t\tlibWrapper.register(SETTINGS.MOD_NAME, 'ChatLog.prototype._onChatKeyDown', (wrapper: (..._: any) => void, ...args: any) => {\n\t\t\tconst event = args[0] as KeyboardEvent;\n\t\t\t// We have used the Shift+Up combo to edit previously sent message\n\t\t\tif (event.code === \"ArrowUp\" && event.ctrlKey) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tlet messages = <(ChatMessageData & ChatMessage)[]><any[]>[...(ui.chat.collection.values())];\n\t\t\t\t// Perform an inverted sort ( n<0 before, n=0 same, n>0 after )\n\t\t\t\tmessages = messages.sort((a, b) => b.timestamp - a.timestamp);\n\t\t\t\tconst message = messages.find(x => x.user === game.user.id);\n\t\t\t\tif (!message) return;\n\t\t\t\tDFChatEdit.editChatMessage.bind(message)();\n\t\t\t}\n\t\t\telse\n\t\t\t\twrapper(...args);\n\t\t}, 'MIXED');\n\n\t\tlibWrapper.register(SETTINGS.MOD_NAME, 'ChatLog.prototype.processMessage', function (this: ChatLog, wrapper: AnyFunction, message: string) {\n\t\t\tlet originalMessage: string = null;\n\t\t\tif (SETTINGS.get(DFChatEditor.PREF_MARKDOWN)) {\n\t\t\t\tif (message.trim().startsWith('/')) {\n\t\t\t\t\tconst token = message.split(' ')[0].trim();\n\t\t\t\t\tswitch (token) {\n\t\t\t\t\t\tcase '/ooc': /* fall-through */\n\t\t\t\t\t\tcase '/ic': /* fall-through */\n\t\t\t\t\t\tcase '/emote': /* fall-through */\n\t\t\t\t\t\tcase '/whisper': /* fall-through */\n\t\t\t\t\t\tcase '/w':\n\t\t\t\t\t\t\t[originalMessage, message] = DFChatEditor.processMarkdown(message.substr(token.length));\n\t\t\t\t\t\t\toriginalMessage = `${token} ${originalMessage.trimStart()}`;\n\t\t\t\t\t\t\tmessage = `${token} ${message.trimStart()}`;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'log': /* fall-through */\n\t\t\t\t\t\tcase 'gmlog': /* fall-through */\n\t\t\t\t\t\tcase '/gmroll': /* fall-through */\n\t\t\t\t\t\tcase '/blindroll': /* fall-through */\n\t\t\t\t\t\tcase '/selfroll': /* fall-through */\n\t\t\t\t\t\tcase '/r': /* fall-through */\n\t\t\t\t\t\tcase '/roll': /* fall-through */\n\t\t\t\t\t\tdefault: break;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t[originalMessage, message] = DFChatEditor.processMarkdown(message);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst result = wrapper(message);\n\t\t\tif (originalMessage) {\n\t\t\t\tthis._sentMessages.splice(0, 1);\n\t\t\t\tthis._sentMessages.unshift(originalMessage);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, 'WRAPPER');\n\t}\n\n\tstatic appendChatContextMenuOptions(options: ContextMenu.Item[]) {\n\t\toptions.push({\n\t\t\tname: 'DF_CHAT_EDIT.ContextOption',\n\t\t\ticon: '<i class=\"fas fa-pencil-alt\"></i>',\n\t\t\tcondition: (header) => {\n\t\t\t\tconst chatData = <ChatMessageData & ChatMessage><any>ui.chat.collection.get($(header).attr('data-message-id'));\n\t\t\t\treturn this.processChatMessage(chatData);\n\t\t\t},\n\t\t\tcallback: (header) => {\n\t\t\t\tconst chatData = <ChatMessageData & ChatMessage><any>ui.chat.collection.get($(header).attr('data-message-id'));\n\t\t\t\tDFChatEdit.editChatMessage.bind(chatData)();\n\t\t\t\treturn {};\n\t\t\t}\n\t\t});\n\t}\n\n\t// Will be bound to the instance of ChatMessage we are observing\n\tstatic async editChatMessage(this: ChatMessageData & ChatMessage) {\n\t\t// Double check permissions\n\t\tif (!SETTINGS.get(PREF_EDIT_ALLOWED)) {\n\t\t\tui.notifications.warn('DF_CHAT_EDIT.Error_NoPermission'.localize());\n\t\t\treturn;\n\t\t}\n\t\tif ((<any>this).chatEditor) {\n\t\t\t(<any>this).chatEditor.bringToTop();\n\t\t} else {\n\t\t\t(<any>this).chatEditor = new DFChatEditor(this);\n\t\t\tawait (<any>this).chatEditor._render(true);\n\t\t}\n\t\t(<any>this).chatEditor.element.find('textarea').focus();\n\t}\n\n\tstatic isHTML(str: string): boolean {\n\t\tconst doc = new DOMParser().parseFromString(str, \"text/html\");\n\t\treturn Array.from(doc.body.childNodes).some(node => {\n\t\t\treturn (node instanceof HTMLElement && !node.classList.contains('df-edited'))\n\t\t\t\t&& !(node instanceof HTMLBRElement)\n\t\t\t\t&& node.nodeType === 1;\n\t\t});\n\t}\n\n\tstatic processChatMessage(chatMessage: ChatMessageData & ChatMessage/*, html: JQuery<HTMLElement>*/): boolean {\n\t\t// If we are catching the render of an archived message\n\t\tif (!ui.chat.collection.has(chatMessage.id))\n\t\t\treturn false;\n\t\t// Ignore rolls and other people's messages, unless we are the GM and PREF_GM_ALL is true\n\t\tif (!SETTINGS.get(PREF_EDIT_ALLOWED) || chatMessage.isRoll\n\t\t\t|| (chatMessage.user.id !== game.userId && !(game.user.isGM && SETTINGS.get(PREF_GM_ALL))))\n\t\t\treturn false;\n\t\t// If we ignore html and message contains html, return\n\t\tif (SETTINGS.get(PREF_IGNORE_HTML) && DFChatEdit.isHTML(chatMessage.content)) return false;\n\t\treturn true;\n\t}\n}\n","import SETTINGS from \"../../../common/Settings\";\n\nexport default class FontSizePatch {\n\n\tprivate static readonly PREF_SIZE = 'FontSizePatch.FontSize';\n\n\tstatic init() {\n\t\tSETTINGS.register<number>(this.PREF_SIZE, {\n\t\t\tname: 'DF_CHAT_FONT_SIZE.FontSizeName'.localize(),\n\t\t\thint: 'DF_CHAT_FONT_SIZE.FontSizeHint'.localize(),\n\t\t\tconfig: true,\n\t\t\ttype: Number,\n\t\t\tscope: 'client',\n\t\t\trange: {\n\t\t\t\tmin: 10,\n\t\t\t\tmax: 30,\n\t\t\t\tstep: 0.5\n\t\t\t},\n\t\t\tdefault: 14,\n\t\t\tonChange: (newSize) => this.updateFontSize(newSize)\n\t\t});\n\t\tthis.updateFontSize(SETTINGS.get<number>(this.PREF_SIZE));\n\t}\n\n\tprivate static updateFontSize(size: number) {\n\t\t(<HTMLElement>document.querySelector(':root')).style.setProperty('--dfce-chat-font-size', size.toString() + 'px');\n\t}\n}","import SETTINGS from \"../../../common/Settings\";\nimport DFAdventureLogProcessor from \"./DFAdventureLogProcessor\";\n\n\nexport default class DFAdventureLogConfig extends FormApplication {\n\tstatic readonly PREF_JOURNAL = 'log-journal';\n\tstatic readonly PREF_JOURNAL_GM = 'gmlog-journal';\n\tstatic readonly PREF_CONFIG = 'log-config-menu';\n\n\tstatic get defaultOptions() {\n\t\treturn mergeObject(FormApplication.defaultOptions as Partial<FormApplicationOptions>, {\n\t\t\ttemplate: \"modules/df-chat-enhance/templates/log-config.hbs\",\n\t\t\tresizable: false,\n\t\t\tminimizable: false,\n\t\t\ttitle: \"DF_CHAT_LOG.Config_Title\".localize()\n\t\t}) as FormApplicationOptions;\n\t}\n\n\tstatic setupSettings() {\n\t\tSETTINGS.register(DFAdventureLogConfig.PREF_JOURNAL, {\n\t\t\tscope: 'world',\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t\tconfig: false\n\t\t});\n\t\tSETTINGS.register(DFAdventureLogConfig.PREF_JOURNAL_GM, {\n\t\t\tscope: 'world',\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t\tconfig: false\n\t\t});\n\t\tSETTINGS.registerMenu(DFAdventureLogConfig.PREF_CONFIG, {\n\t\t\trestricted: true,\n\t\t\ttype: <any>DFAdventureLogConfig,\n\t\t\tlabel: \"DF_CHAT_LOG.Config_Title\",\n\t\t\ticon: 'fas fa-edit'\n\t\t});\n\t}\n\n\tgetData(options?: any) {\n\t\tconst data = super.getData(options);\n\t\tconst keys = game.journal.contents.filter(x => x.pages.contents.some(y => y.type === 'text')).map(x => x.id);\n\t\tconst selectedLog = (SETTINGS.get(DFAdventureLogConfig.PREF_JOURNAL) as string | undefined)?.split('.');\n\t\tconst selectedGMLog = (SETTINGS.get(DFAdventureLogConfig.PREF_JOURNAL_GM) as string | undefined)?.split('.');\n\t\tlet logJournals: any[] = [];\n\t\tlet logJournalPages: any[] = [];\n\t\tlet gmlogJournals: any[] = [];\n\t\tlet gmlogJournalPages: any[] = [];\n\t\tfor (const key of keys) {\n\t\t\tlogJournals.push({\n\t\t\t\tid: key,\n\t\t\t\tname: game.journal.get(key).name,\n\t\t\t\tselected: selectedLog && key === selectedLog[0]\n\t\t\t});\n\t\t\tif (selectedLog && key === selectedLog[0]) {\n\t\t\t\tlogJournalPages = game.journal.get(key).pages.contents.map(x => ({\n\t\t\t\t\tid: key + '.' + x.id,\n\t\t\t\t\tname: x.name,\n\t\t\t\t\tselected: x.id === selectedLog[1]\n\t\t\t\t}));\n\t\t\t}\n\t\t\tgmlogJournals.push({\n\t\t\t\tid: key,\n\t\t\t\tname: game.journal.get(key).name,\n\t\t\t\tselected: selectedGMLog && key === selectedGMLog[0]\n\t\t\t});\n\t\t\tif (selectedGMLog && key === selectedGMLog[0]) {\n\t\t\t\tgmlogJournalPages = game.journal.get(key).pages.contents.map(x => ({\n\t\t\t\t\tid: key + '.' + x.id,\n\t\t\t\t\tname: x.name,\n\t\t\t\t\tselected: x.id === selectedGMLog[1]\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t\tlogJournals = logJournals.sort((a, b) => a.name.localeCompare(b.name));\n\t\tgmlogJournals = gmlogJournals.sort((a, b) => a.name.localeCompare(b.name));\n\n\t\tmergeObject(data as any, {\n\t\t\tlogJournals,\n\t\t\tlogJournalPages,\n\t\t\tgmlogJournals,\n\t\t\tgmlogJournalPages\n\t\t});\n\t\treturn data;\n\t}\n\n\tprivate fillPageList(journalId: string, element: JQuery<HTMLSelectElement>) {\n\t\telement.children().remove();\n\t\tconst journal = game.journal.get(journalId);\n\t\tif (!journal) return;\n\t\tfor (const page of journal.pages.contents.filter(x => x.type == 'text')) {\n\t\t\telement.append(`<option value=\"${journalId}.${page.id}\">${page.name}</option>`);\n\t\t}\n\t}\n\n\tactivateListeners(html: JQuery<HTMLElement>): void {\n\t\thtml.find('#dfal-journal').on('change', event => {\n\t\t\tconst journalId = (event.currentTarget as HTMLSelectElement).value;\n\t\t\tconst pageElement = html.find<HTMLSelectElement>('#dfal-journal-page');\n\t\t\tthis.fillPageList(journalId, pageElement);\n\t\t});\n\t\thtml.find('#dfal-journal-gm').on('change', event => {\n\t\t\tconst journalId = (event.currentTarget as HTMLSelectElement).value;\n\t\t\tconst pageElement = html.find<HTMLSelectElement>('#dfal-journal-gm-page');\n\t\t\tthis.fillPageList(journalId, pageElement);\n\t\t});\n\t}\n\n\tasync _updateObject(_event?: any, formData?: any) {\n\t\tconst logJournal = formData['dfal-journal-page'];\n\t\tconst gmlogJournal = formData['dfal-journal-gm-page'];\n\t\tconst clear = formData['dfal-clear'];\n\t\tconst gmClear = formData['dfal-clear-gm'];\n\t\tSETTINGS.set(DFAdventureLogConfig.PREF_JOURNAL, logJournal);\n\t\tSETTINGS.set(DFAdventureLogConfig.PREF_JOURNAL_GM, gmlogJournal);\n\t\tawait DFAdventureLogConfig.initializeJournal(logJournal, clear, false, false);\n\t\tawait DFAdventureLogConfig.initializeJournal(gmlogJournal, gmClear, true, false);\n\t}\n\n\tstatic async initializeJournal(id: string, clear: boolean, isGMOnly: boolean, isPlayerLog: boolean) {\n\t\tconst journalId = id?.split('.');\n\t\tif (!journalId || journalId.length < 2 || !game.journal.has(journalId[0])) return;\n\t\tconst journal = game.journal.get(journalId[0]).pages.get(journalId[1]);\n\t\tif (clear || journal.text.content === null)\n\t\t\tjournal.text.content = '';\n\t\tconst html = $(journal.text.content);\n\t\tconst article = html.find('article[class=\"df-adventure-log\"]');\n\t\tif (article.length != 0) {\n\t\t\tawait DFAdventureLogProcessor.resortLog();\n\t\t\treturn;\n\t\t}\n\t\tawait journal.update({\n\t\t\t'text.content': journal.text.content + `\n\t\t\t<section>\n\t\t\t\t<h2>${game.i18n.localize(isGMOnly ? 'DF_CHAT_LOG.GMLog_Header' : isPlayerLog ? 'DF_CHAT_LOG.PLog_Header' : 'DF_CHAT_LOG.Log_Header')}</h2>\n\t\t\t\t<section class=\"df-adventure-log\"></section>\n\t\t\t\t<hr />\n\t\t\t</section>\n\t\t\t`\n\t\t});\n\t}\n}","\nimport { ChatMessageData, ChatMessageDataConstructorData } from \"@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs/chatMessageData\";\nimport SETTINGS from \"../../../common/Settings\";\nimport DFChatEditor from \"../edit/DFChatEditor\";\nimport DFAdventureLogConfig from './DFAdventureLogConfig';\n\ndeclare global {\n\tnamespace SimpleCalendar.api {\n\t\tfunction formatDateTime(time: {\n\t\t\tyear: number,\n\t\t\tmonth: number,\n\t\t\tday: number,\n\t\t\thour: number,\n\t\t\tminute: number,\n\t\t\tsecond: number\n\t\t}): { date: string, time: string }\n\t\tfunction formatDateTime(time: {\n\t\t\tyear: number,\n\t\t\tmonth: number,\n\t\t\tday: number,\n\t\t\thour: number,\n\t\t\tminute: number,\n\t\t\tsecond: number\n\t\t}, format: string): string\n\t\tfunction timestamp(): number\n\t\tfunction timestampToDate(timestamp: number): {\n\t\t\tyear: number,\n\t\t\tmonth: number,\n\t\t\tday: number,\n\t\t\thour: number,\n\t\t\tminute: number,\n\t\t\tsecond: number\n\t\t}\n\t}\n}\n\ndeclare global {\n\tinterface String {\n\t\ttrimStart(): string\n\t}\n}\nif (!String.prototype.trimStart) {\n\tString.prototype.trimStart = function () {\n\t\tconst whitespace = [' ', '\\n', '\\r'];\n\t\tlet index = -1;\n\t\tfor (let c = 0; c < this.length; c++) {\n\t\t\tif (whitespace.every(x => x !== this[c])) break;\n\t\t\tindex = c;\n\t\t}\n\t\treturn this.substr(index + 1);\n\t};\n}\n\ndeclare interface ChatCommand {\n\tcommandKey: string;\n\tshouldDisplayToChat: boolean;\n\tinvokeOnCommand: () => void;\n\tcreatedMessageType: number;\n\ticonClass: string;\n\tdescription: string;\n\tgmOnly: boolean;\n}\n\ndeclare class ChatCommands {\n\t/**\n\t * Registers a Chat Command to be handled\n\t */\n\tregisterCommand(command: ChatCommand): void;\n\t/**\n\t * Deregister a Chat Command\n\t */\n\tderegisterCommand(command: ChatCommand): void;\n\tcreateCommandFromData(data: any): ChatCommand;\n}\n\ndeclare class GameExt extends Game {\n\tchatCommands: ChatCommands;\n}\n\nexport default class DFAdventureLogProcessor {\n\tstatic readonly PREF_ENABLE = 'enable-command';\n\tstatic readonly PREF_GMONLY = 'df-log-gmonly';\n\tstatic readonly PREF_GMONLY_WHISPER = 'df-log-gmonly-whisper';\n\tstatic readonly PREF_MESSAGES = 'df-log-messages';\n\tstatic readonly PREF_SORTDESC = 'df-log-sortdesc';\n\tstatic readonly PREF_DISABLE_FORMATTING = 'df-log-disable-format';\n\tstatic readonly PREF_DISABLE_AUTHOR = 'df-log-disable-author';\n\tstatic readonly PREF_SIMPLE_CALENDAR = 'df-log-use-simple-calendar';\n\tstatic readonly PREF_USE_TIME = 'df-log-use-time';\n\tstatic readonly PREF_PLAYER_LOG_JOURNAL = 'PlayerAdventureLog';\n\tstatic logCommand: ChatCommand = null;\n\tstatic gmlogCommand: ChatCommand = null;\n\tstatic plogCommand: ChatCommand = null;\n\n\tstatic appendChatContextMenuOptions(options: ContextMenu.Item[]) {\n\t\toptions.push({\n\t\t\tname: 'DF_CHAT_LOG.ContextMenu_AsEvent',\n\t\t\ticon: '<i style=\"color:SeaGreen\" class=\"fas fa-edit\"></i>',\n\t\t\tcondition: () => {\n\t\t\t\tconst enabled = SETTINGS.get(DFAdventureLogProcessor.PREF_ENABLE);\n\t\t\t\tconst isGM = game.user.isGM;\n\t\t\t\tconst gmOnly = SETTINGS.get(DFAdventureLogProcessor.PREF_GMONLY);\n\t\t\t\treturn enabled && (!gmOnly || isGM);\n\t\t\t},\n\t\t\tcallback: (header) => {\n\t\t\t\tconst chatData = <ChatMessageData><any>ui.chat.collection.get($(header).attr('data-message-id'));\n\t\t\t\tDFAdventureLogProcessor.commandProcessor(chatData.content, false, false);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t});\n\t\toptions.push({\n\t\t\tname: 'DF_CHAT_LOG.ContextMenu_AsQuote',\n\t\t\ticon: '<i style=\"color:SeaGreen\" class=\"fas fa-quote-right\"></i>',\n\t\t\tcondition: () => {\n\t\t\t\tconst enabled = SETTINGS.get(DFAdventureLogProcessor.PREF_ENABLE);\n\t\t\t\tconst isGM = game.user.isGM;\n\t\t\t\tconst gmOnly = SETTINGS.get(DFAdventureLogProcessor.PREF_GMONLY);\n\t\t\t\treturn enabled && (!gmOnly || isGM);\n\t\t\t},\n\t\t\tcallback: (header) => {\n\t\t\t\tconst chatData = <ChatMessageData><any>ui.chat.collection.get($(header).attr('data-message-id'));\n\t\t\t\tif (chatData.content.trimStart().startsWith('\"'))\n\t\t\t\t\tDFAdventureLogProcessor.commandProcessor('q ' + chatData.content, false, false);\n\t\t\t\telse\n\t\t\t\t\tDFAdventureLogProcessor.commandProcessor(`q \"${game.users.get(chatData.user).name}\" ${chatData.content}`, false, false);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t});\n\t\toptions.push({\n\t\t\tname: 'DF_CHAT_LOG.ContextMenu_AsGmEvent',\n\t\t\ticon: '<i style=\"color:FireBrick\" class=\"fas fa-edit\"></i>',\n\t\t\tcondition: () => {\n\t\t\t\tconst enabled = SETTINGS.get(DFAdventureLogProcessor.PREF_ENABLE);\n\t\t\t\tconst isGM = game.user.isGM;\n\t\t\t\treturn enabled && isGM;\n\t\t\t},\n\t\t\tcallback: (header) => {\n\t\t\t\tconst chatData = <ChatMessageData><any>ui.chat.collection.get($(header).attr('data-message-id'));\n\t\t\t\tDFAdventureLogProcessor.commandProcessor(chatData.content, true, false);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t});\n\t\toptions.push({\n\t\t\tname: 'DF_CHAT_LOG.ContextMenu_AsGmQuote',\n\t\t\ticon: '<i style=\"color:FireBrick\" class=\"fas fa-quote-right\"></i>',\n\t\t\tcondition: () => {\n\t\t\t\tconst enabled = SETTINGS.get(DFAdventureLogProcessor.PREF_ENABLE);\n\t\t\t\tconst isGM = game.user.isGM;\n\t\t\t\treturn enabled && isGM;\n\t\t\t},\n\t\t\tcallback: (header) => {\n\t\t\t\tconst chatData = <ChatMessageData><any>ui.chat.collection.get($(header).attr('data-message-id'));\n\t\t\t\tif (chatData.content.trimStart().startsWith('\"'))\n\t\t\t\t\tDFAdventureLogProcessor.commandProcessor('q ' + chatData.content, true, false);\n\t\t\t\telse\n\t\t\t\t\tDFAdventureLogProcessor.commandProcessor(`q \"${game.users.get(chatData.user).name}\" ${chatData.content}`, true, false);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t});\n\t}\n\n\tstatic setupSettings() {\n\t\tSETTINGS.register(DFAdventureLogProcessor.PREF_ENABLE, {\n\t\t\tscope: 'world',\n\t\t\tname: 'DF_CHAT_LOG.Setting.EnableTitle',\n\t\t\thint: 'DF_CHAT_LOG.Setting.EnableHint',\n\t\t\tconfig: true,\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tonChange: (enabled: boolean) => {\n\t\t\t\tif (!enabled && !!DFAdventureLogProcessor.logCommand)\n\t\t\t\t\tDFAdventureLogProcessor.deregisterCommand();\n\t\t\t\telse\n\t\t\t\t\tDFAdventureLogProcessor.registerCommand();\n\t\t\t}\n\t\t});\n\t\tSETTINGS.register(DFAdventureLogProcessor.PREF_GMONLY, {\n\t\t\tname: 'DF_CHAT_LOG.Setting.GmOnlyTitle',\n\t\t\thint: 'DF_CHAT_LOG.Setting.GmOnlyHint',\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t\tconfig: true,\n\t\t\tonChange: (gmOnly) => {\n\t\t\t\tif (gmOnly && !game.user.isGM)\n\t\t\t\t\tDFAdventureLogProcessor.deregisterCommand();\n\t\t\t\telse\n\t\t\t\t\tDFAdventureLogProcessor.registerCommand();\n\t\t\t}\n\t\t});\n\t\tSETTINGS.register(DFAdventureLogProcessor.PREF_GMONLY_WHISPER, {\n\t\t\tname: 'DF_CHAT_LOG.Setting.GmOnlyWhisperName',\n\t\t\thint: 'DF_CHAT_LOG.Setting.GmOnlyWhisperHint',\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t\tconfig: true\n\t\t});\n\t\tSETTINGS.register(DFAdventureLogProcessor.PREF_USE_TIME, {\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tname: \"DF_CHAT_LOG.Setting.UseTimeName\",\n\t\t\thint: \"DF_CHAT_LOG.Setting.UseTimeHint\",\n\t\t\tdefault: true,\n\t\t\tconfig: true\n\t\t});\n\t\tSETTINGS.register(DFAdventureLogProcessor.PREF_MESSAGES, {\n\t\t\tname: 'DF_CHAT_LOG.Setting.PrintMessagesName',\n\t\t\thint: 'DF_CHAT_LOG.Setting.PrintMessagesHint',\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tconfig: true\n\t\t});\n\t\tSETTINGS.register(DFAdventureLogProcessor.PREF_SORTDESC, {\n\t\t\tname: 'DF_CHAT_LOG.Setting.SortDescendingName',\n\t\t\thint: 'DF_CHAT_LOG.Setting.SortDescendingHint',\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t\tconfig: true,\n\t\t\tonChange: () => this.resortLog()\n\t\t});\n\t\tSETTINGS.register(DFAdventureLogProcessor.PREF_DISABLE_FORMATTING, {\n\t\t\tname: 'DF_CHAT_LOG.Setting.DisableFormatName'.localize(),\n\t\t\thint: 'DF_CHAT_LOG.Setting.DisableFormatHint'.localize(),\n\t\t\tconfig: true,\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tdefault: false\n\t\t});\n\t\tSETTINGS.register(DFAdventureLogProcessor.PREF_DISABLE_AUTHOR, {\n\t\t\tname: 'DF_CHAT_LOG.Setting.DisableEntryAuthorName'.localize(),\n\t\t\thint: 'DF_CHAT_LOG.Setting.DisableEntryAuthorHint'.localize(),\n\t\t\tconfig: true,\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tdefault: false\n\t\t});\n\t\t// If Simple Calendar is enabled\n\t\tif (game.modules.get('foundryvtt-simple-calendar')?.active) {\n\t\t\tSETTINGS.register(DFAdventureLogProcessor.PREF_SIMPLE_CALENDAR, {\n\t\t\t\tscope: 'world',\n\t\t\t\ttype: Boolean,\n\t\t\t\tname: \"DF_CHAT_LOG.Setting.SimpleCalendarName\",\n\t\t\t\thint: \"DF_CHAT_LOG.Setting.SimpleCalendarHint\",\n\t\t\t\tdefault: false,\n\t\t\t\tconfig: true\n\t\t\t});\n\t\t}\n\n\t\tHooks.on('closeDFAdventureLogConfig', () => { DFAdventureLogProcessor.logConfig = null; });\n\t\tif ((game as GameExt).chatCommands)\n\t\t\tDFAdventureLogProcessor.registerCommand();\n\t\telse\n\t\t\tHooks.on('chatCommandsReady', function () { DFAdventureLogProcessor.registerCommand(); });\n\t}\n\n\tstatic deregisterCommand() {\n\t\t(game as GameExt).chatCommands.deregisterCommand(DFAdventureLogProcessor.logCommand);\n\t\t(game as GameExt).chatCommands.deregisterCommand(DFAdventureLogProcessor.plogCommand);\n\t\tif (DFAdventureLogProcessor.gmlogCommand)\n\t\t\t(game as GameExt).chatCommands.deregisterCommand(DFAdventureLogProcessor.gmlogCommand);\n\t\tDFAdventureLogProcessor.logCommand = null;\n\t\tDFAdventureLogProcessor.plogCommand = null;\n\t\tDFAdventureLogProcessor.gmlogCommand = null;\n\t}\n\tstatic registerCommand() {\n\t\tif (!SETTINGS.get(DFAdventureLogProcessor.PREF_ENABLE))\n\t\t\treturn;\n\t\tif (SETTINGS.get(DFAdventureLogProcessor.PREF_GMONLY) && !game.user.isGM)\n\t\t\treturn;\n\t\tif (DFAdventureLogProcessor.logCommand)\n\t\t\treturn;\n\n\t\tDFAdventureLogProcessor.logCommand = (game as GameExt).chatCommands.createCommandFromData({\n\t\t\tcommandKey: \"/log\",\n\t\t\tinvokeOnCommand: async (_cl: any, msg: string, _cd: any) => await DFAdventureLogProcessor.commandProcessor(msg, false, false),\n\t\t\tshouldDisplayToChat: false,\n\t\t\ticonClass: \"fa-edit\",\n\t\t\tdescription: \"DF_CHAT_LOG.CommandDescription\".localize()\n\t\t});\n\t\t(game as GameExt).chatCommands.registerCommand(DFAdventureLogProcessor.logCommand);\n\n\t\tDFAdventureLogProcessor.plogCommand = (game as GameExt).chatCommands.createCommandFromData({\n\t\t\tcommandKey: \"/plog\",\n\t\t\tinvokeOnCommand: async (_cl: any, msg: string, _cd: any) => await DFAdventureLogProcessor.commandProcessor(msg, false, true),\n\t\t\tshouldDisplayToChat: false,\n\t\t\ticonClass: \"fa-edit\",\n\t\t\tdescription: \"DF_CHAT_LOG.PCCommandDescription\".localize()\n\t\t});\n\t\t(game as GameExt).chatCommands.registerCommand(DFAdventureLogProcessor.plogCommand);\n\n\t\t// If we are not the GM, early return to avoid registering the /gmlog command\n\t\tif (!game.user.isGM) return;\n\t\t// Register the /gmlog command\n\t\tDFAdventureLogProcessor.gmlogCommand = (game as GameExt).chatCommands.createCommandFromData({\n\t\t\tcommandKey: \"/gmlog\",\n\t\t\tinvokeOnCommand: async (_cl: any, msg: string, _cd: any) => await DFAdventureLogProcessor.commandProcessor(msg, true, false),\n\t\t\tshouldDisplayToChat: false,\n\t\t\ticonClass: \"fa-edit\",\n\t\t\tdescription: \"DF_CHAT_LOG.GMCommandDescription\".localize()\n\t\t});\n\t\t(game as GameExt).chatCommands.registerCommand(DFAdventureLogProcessor.gmlogCommand);\n\t}\n\n\tprivate static _getTimestamp() {\n\t\tconst useTime = SETTINGS.get(DFAdventureLogProcessor.PREF_USE_TIME);\n\t\tif (game.modules.get('foundryvtt-simple-calendar')?.active && SETTINGS.get(DFAdventureLogProcessor.PREF_SIMPLE_CALENDAR)) {\n\t\t\tconst stamp = SimpleCalendar.api.formatDateTime(SimpleCalendar.api.timestampToDate(SimpleCalendar.api.timestamp()));\n\t\t\treturn useTime ? `${stamp.date} ${stamp.time}` : stamp.date;\n\t\t}\n\t\telse if (useTime)\n\t\t\treturn new Date().toLocaleString('sv').replace(',', '').replace(/ ([AP])/, '$1');\n\t\telse {\n\t\t\treturn new Date().toLocaleString('sv').replace(',', '').replace(/ ([AP])/, '$1').split(' ')[0];\n\t\t}\n\t}\n\n\tprivate static logConfig: DFAdventureLogConfig = null;\n\tstatic async commandProcessor(messageText: string, gmLog: boolean, isPlayerLog: boolean, preventPostToChat = false): Promise<void> {\n\t\tmessageText = messageText.trim();\n\t\tconst tokens = messageText.split(' ');\n\n\t\tif (!SETTINGS.get(DFAdventureLogProcessor.PREF_ENABLE)) {\n\t\t\t(game as GameExt).chatCommands.deregisterCommand(DFAdventureLogProcessor.logCommand);\n\t\t\tui.notifications.warn('DF_CHAT_LOG.Error.Disabled'.localize());\n\t\t\treturn;\n\t\t}\n\n\t\t// If the user did not enter anything, send them a help message\n\t\tif (messageText.length == 0 || tokens.every(x => x.length == 0)) {\n\t\t\tsetTimeout(async () => {\n\t\t\t\tawait Dialog.prompt({\n\t\t\t\t\ttitle: 'DF_CHAT_LOG.HelpDialog_Title'.localize(),\n\t\t\t\t\tlabel: 'OK',\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-empty-function\n\t\t\t\t\tcallback: () => { },\n\t\t\t\t\tcontent: await renderTemplate(`modules/df-chat-enhance/templates/lang/log-help.${'DF_CHAT_ENHANCE.LANG'.localize()}.hbs`, {\n\t\t\t\t\t\tisGM: game.user.isGM\n\t\t\t\t\t}),\n\t\t\t\t\toptions: { width: 800 }\n\t\t\t\t});\n\t\t\t}, 1);\n\t\t\treturn;\n\t\t}\n\n\t\tconst speaker = ChatMessage.getSpeaker(<any>{ user: game.user });\n\t\tconst messageData: DeepPartial<ChatMessageDataConstructorData> = {\n\t\t\tflavor: '',\n\t\t\tuser: game.user.id,\n\t\t\tspeaker: speaker,\n\t\t\ttype: CONST.CHAT_MESSAGE_TYPES.OOC,\n\t\t\tcontent: '',\n\t\t};\n\t\tlet line: string;\n\t\tconst disableFormatting = SETTINGS.get(DFAdventureLogProcessor.PREF_DISABLE_FORMATTING);\n\t\tconst disableAuthor = isPlayerLog || SETTINGS.get(DFAdventureLogProcessor.PREF_DISABLE_AUTHOR);\n\t\tswitch (tokens[0].toLowerCase()) {\n\t\t\tcase 'config':\n\t\t\t\tif (!game.user.isGM) {\n\t\t\t\t\tui.notifications.warn('DF_CHAT_LOG.Error.ConfigGmOnly'.localize());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetTimeout(async () => {\n\t\t\t\t\tif (DFAdventureLogProcessor.logConfig)\n\t\t\t\t\t\tDFAdventureLogProcessor.logConfig.bringToTop();\n\t\t\t\t\telse {\n\t\t\t\t\t\tDFAdventureLogProcessor.logConfig = new DFAdventureLogConfig({});\n\t\t\t\t\t\tDFAdventureLogProcessor.logConfig.render(true);\n\t\t\t\t\t}\n\t\t\t\t}, 1);\n\t\t\t\treturn;\n\t\t\tcase 'q':\n\t\t\tcase 'quote':\n\t\t\t\tmessageText = messageText.replace(tokens[0], '').trimStart();\n\t\t\t\tlet source: string;\n\t\t\t\t// If the token starts with a quote, but does not end with one\n\t\t\t\tif (tokens[1][0] === '\"' && tokens[1][tokens[1].length - 1] !== '\"') {\n\t\t\t\t\t// Extract the quoted Source\n\t\t\t\t\tlet index = -1;\n\t\t\t\t\tfor (let c = 1; c < messageText.length; c++) {\n\t\t\t\t\t\tif (messageText[c] === '\"') {\n\t\t\t\t\t\t\tindex = c;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (index < 0) {\n\t\t\t\t\t\tui.notifications.error('DF_CHAT_LOG.Error.MissingQuote'.localize().replace('{0}', tokens[1]));\n\t\t\t\t\t\tsetTimeout(() => $('#chat-message').val('/log q ' + messageText), 1);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tsource = messageText.slice(0, index + 1);\n\t\t\t\t\tmessageText = messageText.slice(index + 1).trimStart();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tsource = tokens[1];\n\t\t\t\tmessageText = DFChatEditor.processMarkdown(messageText)[1].replace(source, '').trim();\n\t\t\t\t// Remove any double-quotes surrounding the source token\n\t\t\t\tsource = source.replace(/\"/gm, '');\n\t\t\t\tmessageData.flavor = `${game.user.name} quoted ${source}`;\n\t\t\t\tmessageData.content = `<span class=\"dfal-qu\">${messageText}</span>`;\n\t\t\t\tif (messageText.length == 0) {\n\t\t\t\t\tui.notifications.error('DF_CHAT_LOG.Error.MissingMessage'.localize());\n\t\t\t\t\tsetTimeout(() => $('#chat-message').val(`/log q \"${source}\" ${messageText}`), 1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tline = 'DF_CHAT_LOG.Log_Quote';\n\t\t\t\tif (disableFormatting) line += '_Bland';\n\t\t\t\tif (disableAuthor) line += '_NoAuth';\n\t\t\t\tline = line.localize();\n\t\t\t\tline = line.replace('{0}', this._getTimestamp());\n\t\t\t\tline = line.replace('{1}', game.user.name);\n\t\t\t\tline = line.replace('{2}', source);\n\t\t\t\tmessageText = line.replace('{3}', messageText);\n\t\t\t\tbreak;\n\t\t\tcase 'e':\n\t\t\tcase 'event':\n\t\t\t\tmessageText = messageText.replace(tokens[0], '').trim();\n\t\t\t// fallthrough\n\t\t\tdefault:\n\t\t\t\tmessageText = DFChatEditor.processMarkdown(messageText)[1].trim();\n\t\t\t\tmessageData.flavor = 'Event Logged';\n\t\t\t\tmessageData.content = `<span class=\"dfal-ev\">${messageText}</span>`;\n\t\t\t\tline = 'DF_CHAT_LOG.Log_Event';\n\t\t\t\tif (disableFormatting) line += '_Bland';\n\t\t\t\tif (disableAuthor) line += '_NoAuth';\n\t\t\t\tline = line.localize();\n\t\t\t\tline = line.replace('{0}', this._getTimestamp());\n\t\t\t\tline = line.replace('{1}', game.user.name);\n\t\t\t\tmessageText = line.replace('{2}', messageText);\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// fetch the log to submit to\n\t\tconst journalId = (isPlayerLog ? game.user.getFlag(SETTINGS.MOD_NAME, this.PREF_PLAYER_LOG_JOURNAL) as string :\n\t\t\tSETTINGS.get<string>(gmLog ? DFAdventureLogConfig.PREF_JOURNAL_GM : DFAdventureLogConfig.PREF_JOURNAL))\n\t\t\t?.split('.');\n\t\tif (!journalId || !game.journal.has(journalId[0])) {\n\t\t\tif (isPlayerLog)\n\t\t\t\tui.notifications.error('DF_CHAT_LOG.Error.NoPlayerJournalSet'.localize());\n\t\t\telse if (game.user.isGM)\n\t\t\t\tui.notifications.error('DF_CHAT_LOG.Error.NoJournalSetGM'.localize(), { permanent: true });\n\t\t\telse\n\t\t\t\tui.notifications.warn('DF_CHAT_LOG.Error.NoJournalSet'.localize());\n\t\t\treturn;\n\t\t}\n\t\tconst journal = game.journal.get(journalId[0]).pages.get(journalId[1]);\n\t\tlet html = $(journal.text.content);\n\t\tconst messageHtml = $(messageText);\n\t\tlet section = html.find('section.df-adventure-log');\n\t\tif (section.length == 0) {\n\t\t\tawait DFAdventureLogConfig.initializeJournal(journalId.join('.'), false, gmLog, isPlayerLog);\n\t\t\thtml = $(journal.text.content);\n\t\t\tsection = html.find('section.df-adventure-log');\n\t\t}\n\t\tconst descending = SETTINGS.get(this.PREF_SORTDESC) as boolean;\n\t\tif (descending) section.prepend(messageHtml); else section.append(messageHtml);\n\t\tawait journal.update({ 'text.content': $('<div></div>').append(html).html() });\n\t\tconst rollType = game.settings.get(\"core\", \"rollMode\");\n\t\tif (game.user.isGM) {\n\t\t\tif (\n\t\t\t\t// If the roll type is anything but Public\n\t\t\t\trollType !== 'publicroll'\n\t\t\t\t// If logs are GM Only and the Whisper All settings is true\n\t\t\t\t|| (SETTINGS.get(DFAdventureLogProcessor.PREF_GMONLY) &&\n\t\t\t\t\tSETTINGS.get(DFAdventureLogProcessor.PREF_GMONLY_WHISPER))\n\t\t\t) {\n\t\t\t\t// Make the message a whisper\n\t\t\t\tmessageData.whisper = [game.user.id];\n\t\t\t}\n\t\t}\n\t\t// All GM and Player logs are whispered\n\t\tif (isPlayerLog || gmLog) {\n\t\t\tmessageData.whisper = [game.user.id];\n\t\t}\n\t\t// Post message to chat if Messages are enabled\n\t\tif (!preventPostToChat && SETTINGS.get(DFAdventureLogProcessor.PREF_MESSAGES))\n\t\t\tawait ChatMessage.create(messageData, {});\n\t}\n\n\tstatic async resortLog() {\n\t\tconst descending = SETTINGS.get(this.PREF_SORTDESC) as boolean;\n\t\tconst journalAll = (SETTINGS.get(DFAdventureLogConfig.PREF_JOURNAL) as string)?.split('.');\n\t\tconst journalGM = (SETTINGS.get(DFAdventureLogConfig.PREF_JOURNAL_GM) as string)?.split('.');\n\n\t\tconst journalSort = async (journal: JournalEntryPage) => {\n\t\t\tconst html = $(journal.text?.content);\n\t\t\tconst article = html.find('article.df-adventure-log');\n\t\t\tconst result = (article.find('p') as any).sort(function (a: HTMLElement, b: HTMLElement) {\n\t\t\t\treturn descending ?\n\t\t\t\t\t$(b).find('span.dfal-ts').text().localeCompare($(a).find('span.dfal-ts').text()) :\n\t\t\t\t\t$(a).find('span.dfal-ts').text().localeCompare($(b).find('span.dfal-ts').text());\n\n\t\t\t});\n\t\t\tarticle.html(result);\n\t\t\tawait journal.update({ 'text.content': $('<div></div>').append(html).html() });\n\t\t};\n\n\t\tif (game.journal.has(journalAll[0]))\n\t\t\tawait journalSort(game.journal.get(journalAll[0]).pages.get(journalAll[1]));\n\t\tif (game.journal.has(journalGM[0]))\n\t\t\tawait journalSort(game.journal.get(journalGM[0]).pages.get(journalGM[1]));\n\t}\n}","import libWrapperShared from \"../../../common/libWrapperShared\";\nimport SETTINGS from \"../../../common/Settings\";\nimport DFAdventureLogConfig from \"./DFAdventureLogConfig\";\nimport DFAdventureLogProcessor from \"./DFAdventureLogProcessor\";\n\ninterface AdventurLogApi {\n\tevent(message: string, postToChat?: boolean): Promise<void>\n\tpevent(message: string, postToChat?: boolean): Promise<void>\n\tgmevent(message: string, postToChat?: boolean): Promise<void>\n\tquote(speaker: string, message: string, postToChat?: boolean): Promise<void>\n\tpquote(speaker: string, message: string, postToChat?: boolean): Promise<void>\n\tgmquote(speaker: string, message: string, postToChat?: boolean): Promise<void>\n}\ndeclare global {\n\tconst AdventureLog: AdventurLogApi;\n}\n\nexport function init() {\n\tconst api: AdventurLogApi = {\n\t\tevent: (async function (message: string, postToChat = false) {\n\t\t\tDFAdventureLogProcessor.commandProcessor('event ' + message, false, false, !postToChat);\n\t\t}).bind(DFAdventureLogProcessor),\n\n\t\tpevent: (async function (message: string, postToChat = false) {\n\t\t\tDFAdventureLogProcessor.commandProcessor('event ' + message, false, true, !postToChat);\n\t\t}).bind(DFAdventureLogProcessor),\n\n\t\tgmevent: (async function (message: string, postToChat = false) {\n\t\t\tif (game.user.isGM)\n\t\t\t\tDFAdventureLogProcessor.commandProcessor('event ' + message, true, false, !postToChat);\n\t\t\telse ui.notifications.warn(\"DF_CHAT_LOG.Error.ApiLog_NotGm\".localize());\n\t\t}).bind(DFAdventureLogProcessor),\n\n\t\tquote: (async function (speaker: string, message: string, postToChat = false) {\n\t\t\tDFAdventureLogProcessor.commandProcessor(`quote \"${speaker}\" ${message}`, false, false, !postToChat);\n\t\t}).bind(DFAdventureLogProcessor),\n\n\t\tpquote: (async function (speaker: string, message: string, postToChat = false) {\n\t\t\tDFAdventureLogProcessor.commandProcessor(`quote \"${speaker}\" ${message}`, false, true, !postToChat);\n\t\t}).bind(DFAdventureLogProcessor),\n\n\t\tgmquote: (async function (speaker: string, message: string, postToChat = false) {\n\t\t\tif (game.user.isGM)\n\t\t\t\tDFAdventureLogProcessor.commandProcessor(`quote \"${speaker}\" ${message}`, true, false, !postToChat);\n\t\t\telse ui.notifications.warn(\"DF_CHAT_LOG.Error.ApiLog_NotGm\".localize());\n\t\t}).bind(DFAdventureLogProcessor)\n\t};\n\t// @ts-expect-error\n\twindow.AdventureLog = api;\n}\nexport function ready() {\n\tif (!game.modules.get('lib-wrapper')?.active) return;\n\tDFAdventureLogConfig.setupSettings();\n\tDFAdventureLogProcessor.setupSettings();\n\n\tHooks.on('renderUserConfig', (_app: UserConfig, html: JQuery<HTMLElement>, data: UserConfig.Data<any>) => {\n\t\tconst journal = (<string>data.user.getFlag(SETTINGS.MOD_NAME, DFAdventureLogProcessor.PREF_PLAYER_LOG_JOURNAL))?.split('.');\n\t\tconst template = Handlebars.compile(`\n<div class=\"form-group\">\n\t<label for=\"dfce-player-log\">Player Log Journal</label>\n\t<div class=\"form-fields\">\n\t\t<select id=\"dfce-player-log\" name=\"player-log\">\n\t\t\t{{#each journals}}\n\t\t\t<option value=\"{{id}}\" {{#if selected}} selected{{/if}}>{{name}}</option>\n\t\t\t{{/each}}\n\t\t</select>\n\t</div>\n</div>\n<div class=\"form-group\">\n\t<label for=\"dfce-player-log-page\">Player Log Journal Page</label>\n\t<div class=\"form-fields\">\n\t\t<select id=\"dfce-player-log-page\" name=\"player-log-page\">\n\t\t\t{{#each pages}}\n\t\t\t<option value=\"{{id}}\"{{#if selected}} selected{{/if}}>{{name}}</option>\n\t\t\t{{/each}}\n\t\t</select>\n\t</div>\n</div>\n`);\n\t\tconst journals = ui.journal.documents\n\t\t\t.filter(x => x.testUserPermission(data.user, CONST.DOCUMENT_PERMISSION_LEVELS.OBSERVER))\n\t\t\t.filter(x => x.pages.contents.some(y => y.type === 'text'));\n\t\tconst journalSelection = $(template({\n\t\t\tselected: journal ?? '',\n\t\t\tjournals: [{ id: '', name: '---', selected: !journal }].concat(journals.map(x => ({\n\t\t\t\tid: x.id,\n\t\t\t\tname: x.name,\n\t\t\t\tselected: x.id === journal[0]\n\t\t\t}))),\n\t\t\tpages: journal ? journals.find(x => x.id == journal[0]).pages.contents.filter(x => x.type === 'text').map(x => ({\n\t\t\t\tid: x.id,\n\t\t\t\tname: x.name,\n\t\t\t\tselected: x.id === journal[1]\n\t\t\t})) : []\n\t\t}, {\n\t\t\tallowProtoMethodsByDefault: true,\n\t\t\tallowProtoPropertiesByDefault: true\n\t\t}));\n\t\thtml.find('#characters').parent().before(journalSelection);\n\t\tjournalSelection.find('#dfce-player-log').on('change', event => {\n\t\t\tconst journalId = (event.currentTarget as HTMLSelectElement).value;\n\t\t\tconst pageElement = journalSelection.find('#dfce-player-log-page');\n\t\t\tpageElement.children().remove();\n\t\t\tif (!journalId || journalId.length === 0) return;\n\t\t\tfor (const page of game.journal.get(journalId).pages.contents.filter(x => x.type === 'text')) {\n\t\t\t\tpageElement.append(`<option value=\"${journalId}.${page.id}\">${page.name}</option>`);\n\t\t\t}\n\t\t});\n\t});\n\n\tlibWrapperShared.register('UserConfig.prototype._updateObject',\n\t\tasync function (this: UserConfig, wrapped: (...args: any) => any, event: any, formData: { \"player-log-page\": string }) {\n\t\t\tawait this.object.setFlag(SETTINGS.MOD_NAME, DFAdventureLogProcessor.PREF_PLAYER_LOG_JOURNAL, formData[\"player-log-page\"]);\n\t\t\treturn await wrapped(event, formData);\n\t\t});\n\n\tmigrateDataV9toV10();\n}\n\nasync function migrateDataV9toV10() {\n\tif (!game.user.isGM) return;\n\tlet journalId = SETTINGS.get<string>(DFAdventureLogConfig.PREF_JOURNAL);\n\tif (checkJournal(journalId))\n\t\tawait SETTINGS.set<string>(DFAdventureLogConfig.PREF_JOURNAL, await migrateJournalV9toV10(journalId));\n\tjournalId = SETTINGS.get<string>(DFAdventureLogConfig.PREF_JOURNAL_GM);\n\tif (checkJournal(journalId))\n\t\tawait SETTINGS.set<string>(DFAdventureLogConfig.PREF_JOURNAL_GM, await migrateJournalV9toV10(journalId));\n\n\tfor (const user of game.users) {\n\t\tjournalId = <string>user.getFlag(SETTINGS.MOD_NAME, DFAdventureLogProcessor.PREF_PLAYER_LOG_JOURNAL);\n\t\tif (!checkJournal(journalId)) continue;\n\t\tjournalId = await migrateJournalV9toV10(journalId);\n\t\tif (!journalId)\n\t\t\tawait user.unsetFlag(SETTINGS.MOD_NAME, DFAdventureLogProcessor.PREF_PLAYER_LOG_JOURNAL);\n\t\telse\n\t\t\tawait user.setFlag(SETTINGS.MOD_NAME, DFAdventureLogProcessor.PREF_PLAYER_LOG_JOURNAL, journalId);\n\t}\n}\n\nfunction checkJournal(id: string) { return id && id.split('.').length < 2; }\n\nasync function migrateJournalV9toV10(id: string): Promise<string | null> {\n\tconst journal = game.journal.get(id);\n\tif (!journal) return null;\n\tconst page = journal.pages.contents.find(x => x.type == 'text');\n\tif (!page) return null;\n\treturn journal.id + '.' + page.id;\n}\n","import { ChatMessageData } from \"@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs\";\nimport libWrapperShared from \"../../../common/libWrapperShared\";\nimport SETTINGS from \"../../../common/Settings\";\nimport DFChatArchiveManager from \"../archive/DFChatArchiveManager\";\n\n\nexport default class ChatMerge {\n\n\tprivate static readonly PREF_ENABLED = 'chat-merge-enabled';\n\tprivate static readonly PREF_SPLIT_SPEAKER = 'chat-merge-split-speaker';\n\tprivate static readonly PREF_EPOCH = 'chat-merge-epoch';\n\tprivate static readonly PREF_ALLOW_ROLLS = 'chat-merge-allowRolls';\n\tprivate static readonly PREF_SEPARATE = 'chat-merge-separateWithBorder';\n\tprivate static readonly PREF_HOVER = 'chat-merge-showhover';\n\tprivate static readonly PREF_SHOW_HEADER = 'chat-merge-showheader';\n\n\tprivate static get _enabled(): boolean { return SETTINGS.get(this.PREF_ENABLED); }\n\tprivate static get _epoch(): number { return SETTINGS.get(this.PREF_EPOCH); }\n\tprivate static get _allowRolls(): string { return SETTINGS.get(this.PREF_ALLOW_ROLLS); }\n\tprivate static get _separateWithBorder(): boolean { return SETTINGS.get(this.PREF_SEPARATE); }\n\tprivate static get _showHover(): boolean { return SETTINGS.get(this.PREF_HOVER); }\n\tprivate static get _showHeader(): boolean { return SETTINGS.get(this.PREF_SHOW_HEADER); }\n\n\tstatic init() {\n\t\tSETTINGS.register(this.PREF_ENABLED, {\n\t\t\tname: 'DF_CHAT_MERGE.EnableName',\n\t\t\thint: 'DF_CHAT_MERGE.EnableHint',\n\t\t\tconfig: true,\n\t\t\tscope: 'client',\n\t\t\tdefault: true,\n\t\t\ttype: Boolean,\n\t\t\tonChange: () => this._processAllMessage()\n\t\t});\n\t\tSETTINGS.register(this.PREF_SHOW_HEADER, {\n\t\t\tname: 'DF_CHAT_MERGE.ShowHeaderName',\n\t\t\thint: 'DF_CHAT_MERGE.ShowHeaderHint',\n\t\t\tconfig: true,\n\t\t\tscope: 'client',\n\t\t\tdefault: false,\n\t\t\ttype: Boolean,\n\t\t\tonChange: (newValue: boolean) => {\n\t\t\t\tconst style = (<HTMLElement>document.querySelector(':root')).style;\n\t\t\t\tstyle.setProperty('--dfce-cm-header', newValue ? '' : 'none');\n\t\t\t\tif (game.user.isGM) {\n\t\t\t\t\tstyle.setProperty('--dfce-cm-header-delete', newValue ? '' : '0');\n\t\t\t\t\tstyle.setProperty('--dfce-cm-header-delete-pad', newValue ? '' : '16px');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tSETTINGS.register(this.PREF_SPLIT_SPEAKER, {\n\t\t\tname: 'DF_CHAT_MERGE.SplitSpeakerName',\n\t\t\thint: 'DF_CHAT_MERGE.SplitSpeakerHint',\n\t\t\tconfig: true,\n\t\t\tscope: 'client',\n\t\t\tdefault: true,\n\t\t\ttype: Boolean,\n\t\t\tonChange: () => this._processAllMessage()\n\t\t});\n\t\tSETTINGS.register<string>(this.PREF_ALLOW_ROLLS, {\n\t\t\tname: 'DF_CHAT_MERGE.AllowRollsName',\n\t\t\thint: 'DF_CHAT_MERGE.AllowRollsHint',\n\t\t\tconfig: true,\n\t\t\tscope: 'client',\n\t\t\tdefault: 'rolls',\n\t\t\ttype: String,\n\t\t\tchoices: {\n\t\t\t\tnone: 'DF_CHAT_MERGE.AllowRollsOptions.none'.localize(),\n\t\t\t\trolls: 'DF_CHAT_MERGE.AllowRollsOptions.rolls'.localize(),\n\t\t\t\tall: 'DF_CHAT_MERGE.AllowRollsOptions.all'.localize()\n\t\t\t},\n\t\t\tonChange: () => this._processAllMessage()\n\t\t});\n\t\tSETTINGS.register(this.PREF_SEPARATE, {\n\t\t\tname: 'DF_CHAT_MERGE.SeparateName',\n\t\t\thint: 'DF_CHAT_MERGE.SeparateHint',\n\t\t\tconfig: true,\n\t\t\tscope: 'client',\n\t\t\tdefault: false,\n\t\t\ttype: Boolean,\n\t\t\tonChange: (newValue: boolean) => {\n\t\t\t\tconst style = (<HTMLElement>document.querySelector(':root')).style;\n\t\t\t\tstyle.setProperty('--dfce-cm-separation', newValue ? '' : '0');\n\t\t\t}\n\t\t});\n\t\tSETTINGS.register(this.PREF_HOVER, {\n\t\t\tname: 'DF_CHAT_MERGE.HoverName',\n\t\t\thint: 'DF_CHAT_MERGE.HoverHint',\n\t\t\tconfig: true,\n\t\t\tscope: 'client',\n\t\t\tdefault: true,\n\t\t\ttype: Boolean,\n\t\t\tonChange: (newValue: boolean) => {\n\t\t\t\tconst style = (<HTMLElement>document.querySelector(':root')).style;\n\t\t\t\tnewValue ? style.removeProperty('--dfce-cm-hover-shadow') : style.setProperty('--dfce-cm-hover-shadow', '0px');\n\t\t\t}\n\t\t});\n\t\tSETTINGS.register<number>(this.PREF_EPOCH, {\n\t\t\tname: 'DF_CHAT_MERGE.EpochName',\n\t\t\thint: 'DF_CHAT_MERGE.EpochHint',\n\t\t\tconfig: true,\n\t\t\tscope: 'client',\n\t\t\tdefault: 10,\n\t\t\ttype: Number,\n\t\t\trange: {\n\t\t\t\tmin: 1,\n\t\t\t\tmax: 60,\n\t\t\t\tstep: 1\n\t\t\t},\n\t\t\tonChange: () => this._processAllMessage()\n\t\t});\n\n\t\tlibWrapperShared.register('ChatLog.prototype.deleteMessage', this._deleteMessage.bind(this));\n\t\tHooks.on(\"renderChatMessage\", this._renderChatMessage);\n\t}\n\tstatic ready() {\n\t\tconst style = (<HTMLElement>document.querySelector(':root')).style;\n\t\tstyle.setProperty('--dfce-cm-separation', this._separateWithBorder ? '' : '0');\n\t\tthis._showHover ? style.removeProperty('--dfce-cm-hover-shadow') : style.setProperty('--dfce-cm-hover-shadow', '0px');\n\t\tstyle.setProperty('--dfce-cm-header', this._showHeader ? '' : 'none');\n\t\tif (game.user.isGM) {\n\t\t\tstyle.setProperty('--dfce-cm-header-delete', this._showHeader ? '' : '0');\n\t\t\tstyle.setProperty('--dfce-cm-header-delete-pad', this._showHeader ? '' : '16px');\n\t\t}\n\t\tthis._processAllMessage(ui.chat.element);\n\t\tHooks.on('renderChatLog', (_: any, html: JQuery<HTMLElement>) => this._processAllMessage(html));\n\t\tHooks.on('renderDFChatArchiveViewer', (_: any, html: JQuery<HTMLElement>) => this._processAllMessage(html));\n\t}\n\n\tprivate static _deleteMessage(wrapper: (arg0: any, arg1: any) => any, messageId: string, { deleteAll = false } = {}) {\n\t\t// Ignore the Delete All process. Everything is being obliterated, who cares about the styling\n\t\tif (!deleteAll && this._enabled) {\n\t\t\tconst element = document.querySelector(`li[data-message-id=\"${messageId}\"`);\n\t\t\t// If we were a TOP\n\t\t\tif (element?.classList?.contains('dfce-cm-top')) {\n\t\t\t\telement.classList.remove('dfce-cm-top');\n\t\t\t\t// If the next element was a middle, make it a top\n\t\t\t\tif (element.nextElementSibling.classList.contains('dfce-cm-middle')) {\n\t\t\t\t\telement.nextElementSibling.classList.remove('dfce-cm-middle');\n\t\t\t\t\telement.nextElementSibling.classList.add('dfce-cm-top');\n\t\t\t\t}\n\t\t\t\t// Otherwise, it was a bottom and should now become a normal message again\n\t\t\t\telse element.nextElementSibling.classList.remove('dfce-cm-bottom');\n\t\t\t}\n\t\t\t// If we were a BOTTOM\n\t\t\telse if (element?.classList?.contains('dfce-cm-bottom')) {\n\t\t\t\telement.classList.remove('dfce-cm-bottom');\n\t\t\t\t// If the previous element was a middle, make it a bottom\n\t\t\t\tif (element.previousElementSibling.classList.contains('dfce-cm-middle')) {\n\t\t\t\t\telement.previousElementSibling.classList.remove('dfce-cm-middle');\n\t\t\t\t\telement.previousElementSibling.classList.add('dfce-cm-bottom');\n\t\t\t\t}\n\t\t\t\t// Otherwise, it was a top and should now become a normal message again\n\t\t\t\telse element.previousElementSibling.classList.remove('dfce-cm-top');\n\t\t\t}\n\t\t\t// If we were a MIDDLE, let the above and below snug and they'll be fine\n\t\t\telse if (element?.classList?.contains('dfce-cm-middle'))\n\t\t\t\telement.classList.remove('dfce-cm-middle');\n\t\t}\n\t\treturn wrapper(messageId, { deleteAll });\n\t}\n\n\tprivate static _processAllMessage(element?: JQuery<HTMLElement>) {\n\t\telement = element ?? $(document.body);\n\t\t// Remove the old CSS class designations\n\t\telement.find('.dfce-cm-top').removeClass('dfce-cm-top');\n\t\telement.find('.dfce-cm-middle').removeClass('dfce-cm-middle');\n\t\telement.find('.dfce-cm-bottom').removeClass('dfce-cm-bottom');\n\t\t// If we are disabled, return\n\t\tif (!ChatMerge._enabled) return;\n\t\t// Collect all rendered chat messages\n\t\tconst messages = element.find('li.chat-message');\n\t\t// Return if there are no messages rendered\n\t\tif (messages.length === 0) return;\n\t\t// Make sure to set the hover colour for the first message since we skip it in the processor bellow.\n\t\tif (messages[0].hasAttribute('style')) {\n\t\t\tmessages[0].style.setProperty('--dfce-mc-border-color', messages[0].style.borderColor);\n\t\t}\n\t\t// Process each message after the first\n\t\tfor (let c = 1; c < messages.length; c++) {\n\t\t\t// Update styling of the chat messages\n\t\t\tthis._styleChatMessages(\n\t\t\t\tgame.messages.get(messages[c].getAttribute('data-message-id')),\n\t\t\t\tmessages[c],\n\t\t\t\tgame.messages.get(messages[c - 1].getAttribute('data-message-id')),\n\t\t\t\tmessages[c - 1]);\n\t\t}\n\t}\n\n\tprivate static _renderChatMessage(message: ChatMessageData, html: JQuery<HTMLElement>, _cmd: ChatMessageData) {\n\t\tif (!ChatMerge._enabled) return;\n\t\t// Find the most recent message in the chat log\n\t\tconst partnerElem = $(`li.chat-message`).last()[0];\n\t\t// If there is no message, return\n\t\tif (partnerElem === null || partnerElem === undefined) return;\n\t\t// get the ChatMessage document associated with the html\n\t\tconst partner = game.messages.get(partnerElem.getAttribute('data-message-id'));\n\t\tif (!message || !partner) return;\n\t\t// Update styling of the chat messages\n\t\tChatMerge._styleChatMessages(message, html[0], partner, partnerElem);\n\t}\n\n\tprivate static _inTimeFrame(current: number, previous: number): boolean {\n\t\treturn current > previous && (current - previous) < (this._epoch * 1000);\n\t}\n\n\tprivate static _isValidMessage(current: ChatMessageData, previous: ChatMessageData): boolean {\n\t\tconst rolls = this._allowRolls;\n\t\tconst splitSpeaker = SETTINGS.get<boolean>(this.PREF_SPLIT_SPEAKER);\n\t\tlet userCompare = false;\n\n\t\tconst currData = current ?? <ChatMessageData><any>current;\n\t\tconst prevData = previous ?? <ChatMessageData><any>previous;\n\n\t\t// If either message is a Midi-QoL message, ignore it\n\t\tif ((currData?.flags && (currData.flags as Record<string, any>)['midi-qol']) || (prevData?.flags && (prevData.flags as Record<string, any>)['midi-qol']))\n\t\t\treturn false;\n\n\t\tif (splitSpeaker) {\n\t\t\t// this is a bit complex, basically we want to group by actors, but if you're not using an actor, group by user instead\n\t\t\tuserCompare = ( // If actors are equal and NOT null\n\t\t\t\tcurrData.speaker.actor === prevData.speaker.actor\n\t\t\t\t&& !!currData.speaker.actor\n\t\t\t) ||\n\t\t\t\t( // If BOTH actors are null and users are equal\n\t\t\t\t\t!currData.speaker.actor\n\t\t\t\t\t&& !prevData.speaker.actor\n\t\t\t\t\t&& currData.user === prevData.user\n\t\t\t\t);\n\t\t} else {\n\t\t\t// If we are not splitting by speaker, just do the simple option of comparing the users\n\t\t\tuserCompare = currData.user === prevData.user;\n\t\t}\n\t\treturn userCompare\n\t\t\t&& this._inTimeFrame(currData.timestamp, prevData.timestamp)\n\t\t\t// Check for merging with roll types\n\t\t\t&& (rolls === 'all'\n\t\t\t\t|| (rolls === 'rolls' && current.isRoll === previous.isRoll)\n\t\t\t\t|| (rolls === 'none' && !current.isRoll && !previous.isRoll));\n\t}\n\n\tprivate static _styleChatMessages(curr: ChatMessageData, currElem: HTMLElement, prev: ChatMessageData, prevElem: HTMLElement) {\n\t\tif (currElem.hasAttribute('style')) {\n\t\t\tcurrElem.style.setProperty('--dfce-mc-border-color', currElem.style.borderColor);\n\t\t}\n\t\t// If we are running in a Chat Archive\n\t\tif (curr === undefined && prev === undefined) {\n\t\t\tconst logId = parseInt(/df-chat-log-(\\d+)/.exec(currElem.parentElement.parentElement.id)[1]);\n\t\t\tif (isNaN(logId)) return;\n\t\t\tconst chatLog = DFChatArchiveManager.chatViewers.get(logId);\n\t\t\tcurr = <ChatMessageData>chatLog.messages.find(x =>\n\t\t\t\t(x.id ?? x._id) == currElem.dataset.messageId);\n\t\t\tprev = <ChatMessageData>chatLog.messages.find(x =>\n\t\t\t\t(x.id ?? x._id) == prevElem.dataset.messageId);\n\t\t}\n\t\tif (!ChatMerge._isValidMessage(curr, prev)) return;\n\t\tif (prevElem.classList.contains('dfce-cm-bottom')) {\n\t\t\tprevElem.classList.remove('dfce-cm-bottom');\n\t\t\tprevElem.classList.add('dfce-cm-middle');\n\t\t} else prevElem.classList.add('dfce-cm-top');\n\t\tcurrElem.classList.add('dfce-cm-bottom');\n\t}\n}","import libWrapperShared from \"../../../common/libWrapperShared\";\nimport SETTINGS from \"../../../common/Settings\";\nimport UTIL from '../Util';\n\nexport default class PlayerColor {\n\tstatic readonly PREF_TINT_BG = 'PlayerColor_TintBackground';\n\tstatic readonly PREF_BORDER_STYLE = 'PlayerColor.BorderStyle';\n\tstatic readonly FLAG_CHAT_COLOR = 'chat-color';\n\n\tstatic init() {\n\t\tSETTINGS.register(PlayerColor.PREF_TINT_BG, {\n\t\t\tconfig: true,\n\t\t\tname: 'DF_CHAT_PLAYER_COLOR.SettingTintBackgroundName',\n\t\t\thint: 'DF_CHAT_PLAYER_COLOR.SettingTintBackgroundHint',\n\t\t\tscope: 'world',\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t\tonChange: UTIL.reloadChatLog\n\t\t});\n\t\tSETTINGS.register<string>(PlayerColor.PREF_BORDER_STYLE, {\n\t\t\tname: 'DF_CHAT_PLAYER_COLOR.SettingBorderStyleName',\n\t\t\thint: 'DF_CHAT_PLAYER_COLOR.SettingBorderStyleHint',\n\t\t\tconfig: true,\n\t\t\ttype: String,\n\t\t\tchoices: {\n\t\t\t\tall: 'DF_CHAT_PLAYER_COLOR.BorderStyle.all',\n\t\t\t\tmine: 'DF_CHAT_PLAYER_COLOR.BorderStyle.mine',\n\t\t\t\tnone: 'DF_CHAT_PLAYER_COLOR.BorderStyle.none'\n\t\t\t},\n\t\t\tdefault: 'all',\n\t\t\tscope: 'client',\n\t\t\tonChange: UTIL.reloadChatLog\n\t\t});\n\n\t\tHooks.on('renderUserConfig', (app: UserConfig, html: JQuery<HTMLElement>, data: UserConfig.Data<any>) => {\n\t\t\tconst color = data.user.getFlag(SETTINGS.MOD_NAME, PlayerColor.FLAG_CHAT_COLOR) ?? '';\n\t\t\thtml.find('input[name=\"color\"]').parent().parent().after(`\n<div class=\"form-group\">\n\t<label for=\"chat-color\">${'DF_CHAT_PLAYER_COLOR.Label'.localize()}</label>\n\t<div class=\"form-fields\">\n\t\t<input class=\"color\" id=\"chat-color\" type=\"text\" name=\"chat-color\" value=\"${color}\">\n\t\t<input type=\"color\" value=\"${color}\" data-edit=\"chat-color\">\n\t</div>\n</div>`);\n\t\t\tconst chatField = html.find('#chat-color');\n\t\t\tconst chatPicker = html.find('[data-edit=\"chat-color\"]');\n\t\t\t// Make sure to update the color selector if a manual entry occurs\n\t\t\tchatField.on('change', () => chatPicker.val(chatField.val()));\n\t\t\t// Resize the window to encompass the new fields\n\t\t\tapp.element[0].style.height = '';\n\t\t\tapp.setPosition({});\n\t\t});\n\n\t\tlibWrapperShared.register('UserConfig.prototype._updateObject',\n\t\t\tasync function (this: UserConfig, wrapped: (arg0: any, arg1: any) => any, event: any, formData: { \"chat-color\": string }): Promise<void> {\n\t\t\t\tawait this.object.setFlag(SETTINGS.MOD_NAME, PlayerColor.FLAG_CHAT_COLOR, formData[\"chat-color\"]);\n\t\t\t\tawait wrapped(event, formData);\n\t\t\t});\n\n\t\tlibWrapper.register(SETTINGS.MOD_NAME, 'ChatMessage.prototype.getHTML', async function (this: ChatMessage, wrapper: (...arg: any) => Promise<JQuery<HTMLElement>>, ...args: any) {\n\t\t\tconst html = await wrapper(...args);\n\t\t\t// If the message has no user bound to it, then it is likely some kind of other message being created by a module. Just return immediately.\n\t\t\tif (!this.user) return html;\n\t\t\tlet chatColor = (<string>this.user.getFlag(SETTINGS.MOD_NAME, PlayerColor.FLAG_CHAT_COLOR))?.trim();\n\t\t\t// If it is a valid color\n\t\t\tif (!chatColor || !/#[a-fA-F0-9]{6,8}/.test(chatColor))\n\t\t\t\tchatColor = this.user.color;\n\n\t\t\t// Set the border colour to its default\n\t\t\tlet borderColour = '#6f6c66';\n\t\t\tswitch (SETTINGS.get<string>(PlayerColor.PREF_BORDER_STYLE)) {\n\t\t\t\tcase 'none': break;\n\t\t\t\tcase 'mine':\n\t\t\t\t\tif (game.userId !== this.data.user) break;\n\t\t\t\t// fallthrough\n\t\t\t\tcase 'all':\n\t\t\t\t\tborderColour = chatColor;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\thtml[0].style.borderColor = borderColour;\n\n\t\t\t// Set the hover border colour to what ever the border colour is\n\t\t\thtml[0].style.setProperty('--dfce-mc-border-color', borderColour);\n\t\t\tif (SETTINGS.get(PlayerColor.PREF_TINT_BG)) {\n\t\t\t\thtml[0].style.backgroundColor = chatColor;\n\t\t\t\thtml[0].style.backgroundImage = 'url(../ui/parchment.jpg)';\n\t\t\t\thtml[0].style.backgroundRepeat = 'repeat';\n\t\t\t\thtml[0].style.backgroundBlendMode = 'screen';\n\t\t\t}\n\t\t\treturn html;\n\t\t}, 'WRAPPER');\n\t}\n}\n","import SETTINGS from \"../../../common/Settings\";\nimport UTIL from \"../Util\";\n\n\nconst ICONS_FOR_KNOWN_ROLL_TYPES: {\n\t[key: string]: string;\n\tpublicroll: string;\n\tgmroll: string;\n\tblindroll: string;\n\tselfroll: string;\n} = {\n\tpublicroll: 'fas fa-dice-d20',\n\tgmroll: 'fas fa-user-secret',\n\tblindroll: 'fas fa-user-ninja',\n\tselfroll: 'fas fa-ghost'\n};\n\ninterface ChatLogData {\n\tuser: User,\n\trollMode: string,\n\trollModes: any,\n\tisStream: boolean\n}\n\nexport default class ChatRollPrivacy {\n\tstatic setup() {\n\t\tgame.keybindings.register(SETTINGS.MOD_NAME, \"roll-mode.publicroll\", {\n\t\t\tname: 'Public Roll',\n\t\t\teditable: [{ key: 'KeyQ', modifiers: [KeyboardManager.MODIFIER_KEYS.ALT] }],\n\t\t\tnamespace: 'Roll Type Shortcuts',\n\t\t\tonDown: () => {\n\t\t\t\t$('#dfcp-rt-buttons > button[data-id=\"publicroll\"]').trigger('click');\n\t\t\t}\n\t\t});\n\t\tgame.keybindings.register(SETTINGS.MOD_NAME, \"roll-mode.gmroll\", {\n\t\t\tname: 'Private GM Roll',\n\t\t\teditable: [{ key: 'KeyW', modifiers: [KeyboardManager.MODIFIER_KEYS.ALT] }],\n\t\t\tnamespace: 'Roll Type Shortcuts',\n\t\t\tonDown: () => {\n\t\t\t\t$('#dfcp-rt-buttons > button[data-id=\"gmroll\"]').trigger('click');\n\t\t\t}\n\t\t});\n\t\tgame.keybindings.register(SETTINGS.MOD_NAME, \"roll-mode.blindroll\", {\n\t\t\tname: 'Blind GM Roll',\n\t\t\teditable: [{ key: 'KeyE', modifiers: [KeyboardManager.MODIFIER_KEYS.ALT] }],\n\t\t\tnamespace: 'Roll Type Shortcuts',\n\t\t\tonDown: () => {\n\t\t\t\t$('#dfcp-rt-buttons > button[data-id=\"blindroll\"]').trigger('click');\n\t\t\t}\n\t\t});\n\t\tgame.keybindings.register(SETTINGS.MOD_NAME, \"roll-mode.selfroll\", {\n\t\t\tname: 'Self Roll',\n\t\t\teditable: [{ key: 'KeyR', modifiers: [KeyboardManager.MODIFIER_KEYS.ALT] }],\n\t\t\tnamespace: 'Roll Type Shortcuts',\n\t\t\tonDown: () => {\n\t\t\t\t$('#dfcp-rt-buttons > button[data-id=\"selfroll\"]').trigger('click');\n\t\t\t}\n\t\t});\n\t}\n\n\tstatic init() {\n\t\tSETTINGS.register('enabled', {\n\t\t\tname: 'DF_CHAT_PRIVACY.Settings_EnableTitle',\n\t\t\thint: 'DF_CHAT_PRIVACY.Settings_EnableHint',\n\t\t\tscope: 'client',\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tconfig: true,\n\t\t\tonChange: UTIL.requestReload\n\t\t});\n\t\tSETTINGS.register('replace-buttons', {\n\t\t\tname: 'DF_CHAT_PRIVACY.Settings_ReplaceButtonsTitle',\n\t\t\thint: 'DF_CHAT_PRIVACY.Settings_ReplaceButtonsHint',\n\t\t\tscope: 'client',\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tconfig: true,\n\t\t\tonChange: UTIL.requestReload\n\t\t});\n\t\n\t\tif (SETTINGS.get('enabled') === false)\n\t\t\treturn;\n\t\n\t\tHooks.on('renderChatLog', this._handleChatLogRendering);\n\t}\n\n\n\tprivate static calcColour(current: number, count: number): string {\n\t\treturn `rgb(${(current / count) * 255},${(1 - (current / count)) * 255},0)`;\n\t}\n\n\tprivate static async _handleChatLogRendering(chat: ChatLog, html: JQuery<HTMLElement>, data: ChatLogData) {\n\t\tconst modes = Object.keys(data.rollModes);\n\t\tconst buttons: any[] = [];\n\t\tconst iconKeys = Object.keys(ICONS_FOR_KNOWN_ROLL_TYPES);\n\t\tfor (let c = 0; c < modes.length; c++) {\n\t\t\tconst rt = modes[c];\n\t\t\tif (!(rt in ICONS_FOR_KNOWN_ROLL_TYPES)) {\n\t\t\t\tconsole.warn(Error(`Unknown roll type '${rt}'`));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbuttons.push({\n\t\t\t\trt: rt,\n\t\t\t\tname: data.rollModes[rt],\n\t\t\t\tactive: data.rollMode === rt,\n\t\t\t\ticon: ICONS_FOR_KNOWN_ROLL_TYPES[rt],\n\t\t\t\tcolour: ChatRollPrivacy.calcColour(iconKeys.findIndex(x => x == rt), iconKeys.length)\n\t\t\t});\n\t\t}\n\t\tconst buttonHtml = $(await renderTemplate('modules/df-chat-enhance/templates/privacy-button.hbs', { buttons }));\n\t\tbuttonHtml.find('button').on('click', function () {\n\t\t\tconst rollType = $(this).attr('data-id');\n\t\t\tgame.settings.set(\"core\", \"rollMode\", <any>rollType);\n\t\t\tbuttonHtml.find('button.active').removeClass('active');\n\t\t\t$(this).addClass('active');\n\t\t});\n\t\thtml.find('select[name=rollMode]').after(buttonHtml);\n\t\thtml.find('select[name=rollMode]').remove();\n\t\n\t\tif (!SETTINGS.get('replace-buttons'))\n\t\t\treturn;\n\t\n\t\t// Adjust the button container to remove the extra margin since those buttons are now moving in.\n\t\tbuttonHtml.attr('style', 'margin:0 0 0 0.5em');\n\t\n\t\t// Convert the old <a> tag elements to <button> tags\n\t\tlet first = true;\n\t\thtml.find('#chat-controls div.control-buttons a').each(function () {\n\t\t\tconst html = $(this).html();\n\t\t\tconst classes = $(this).attr('class');\n\t\t\tconst title = $(this).attr('title');\n\t\t\tconst style = $(this).attr('style');\n\t\t\tconst click = ($ as any)._data(this, 'events')['click'][0].handler;\n\t\t\tconst button = $(`<button class=\"${classes}\" title=\"${title}\" style=\"${style}\">${html}</button>`);\n\t\t\tbutton.on('click', click);\n\t\t\t// Add a small margin between the first button and the RollTypes\n\t\t\tif (first) {\n\t\t\t\tbutton.attr('style', 'margin-left:0.5em');\n\t\t\t\tfirst = false;\n\t\t\t}\n\t\t\tbuttonHtml.append(button);\n\t\t});\n\t\n\t\thtml.find('#chat-controls div.control-buttons').remove();\n\t}\n}\n","import SETTINGS from \"../../../common/Settings\";\nimport UTIL from \"../Util\";\n\nexport default class ChatHistoryOptimizer {\n\n\tprivate static readonly PREF_ENABLED = 'ChatHistoryOptimizer.Enabled';\n\tprivate static readonly PREF_HISTORY_SIZE = 'ChatHistoryOptimizer.HistorySize';\n\n\tstatic init() {\n\n\t\tSETTINGS.register(this.PREF_ENABLED, {\n\t\t\tname: 'DF_CHAT_SCROLL.HistoryFixEnabledName',\n\t\t\thint: 'DF_CHAT_SCROLL.HistoryFixEnabledHint',\n\t\t\tconfig: true,\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tscope: 'world',\n\t\t\tonChange: UTIL.requestReload\n\t\t});\n\t\tSETTINGS.register<number>(this.PREF_HISTORY_SIZE, {\n\t\t\tname: 'DF_CHAT_SCROLL.HistorySizeName',\n\t\t\thint: 'DF_CHAT_SCROLL.HistorySizeHint',\n\t\t\tconfig: true,\n\t\t\ttype: Number,\n\t\t\tdefault: CONFIG.ChatMessage.batchSize,\n\t\t\trange: {\n\t\t\t\tmin: CONFIG.ChatMessage.batchSize,\n\t\t\t\tmax: CONFIG.ChatMessage.batchSize * 5,\n\t\t\t\tstep: CONFIG.ChatMessage.batchSize\n\t\t\t},\n\t\t\tscope: 'world',\n\t\t\tonChange: () => $('#chat-log').trigger('scroll')\n\t\t});\n\n\t\tif (!SETTINGS.get(this.PREF_ENABLED)) return;\n\n\t\tlibWrapper.register(SETTINGS.MOD_NAME, 'ChatLog.prototype._onScrollLog', this._ChatLog_onScrollLog, 'MIXED');\n\n\t\t/**\n\t\t// This is used for DEBUG purposes only\n\t\t// Displays the number of messages being rendered in the Chat Log\n\t\tHooks.on('renderChatLog', (_: any, html: JQuery) => {\n\t\t\thtml.find('#scrollToBottom').after('<div class=\"dfce-chat-count\" style=\"flex:0;text-align:center\"></div>');\n\t\t});\n\t\tthis._displayMessageCounts(0);\n\t\t/**/\n\t}\n\n\tprivate static _ChatLog_onScrollLog(this: ChatLog, wrapped: (event: any) => Promise<void>, event: any): Promise<void> {\n\t\tif (!this.rendered) return Promise.resolve();\n\t\tconst maxMessageCount = SETTINGS.get<number>(ChatHistoryOptimizer.PREF_HISTORY_SIZE);\n\t\t// Ignore all scroll events when there are not enough messages to even batch\n\t\tif (this.collection.size <= CONFIG.ChatMessage.batchSize) return wrapped(event);\n\t\tconst log = event.target as HTMLElement;\n\t\tconst messages = $(log).find('li.chat-message');\n\n\t\t// Grab the top most message based on current scroll position\n\t\tlet topMessageIndex = -1;\n\n\t\t//! NOTICE! The message list is inverted, it is sorted OLDEST to NEWEST,\n\t\t//! so message[0] is at the very top of the chat log, and message[n] is\n\t\t//! at the very bottom of the chat log.\n\n\t\t// We try to start as close to the actual top message as we can, then traverse either up or down from there\n\t\tconst pct = log.scrollTop / log.scrollHeight;\n\t\tconst chatViewTop = log.scrollTop + messages[0].offsetTop;\n\t\tlet c = Math.trunc(messages.length * pct);\n\t\t// If the estimate is too high up the log, we traverse down\n\t\tif (messages[c].offsetTop < chatViewTop) {\n\t\t\tfor (; c < messages.length; c++) {\n\t\t\t\tif (\n\t\t\t\t\t// If this message is at/on the scroll top\n\t\t\t\t\t(messages[c].offsetTop <= chatViewTop && messages[c].offsetTop + messages[c].offsetHeight >= chatViewTop) ||\n\t\t\t\t\t// If the previous message is above the view, and this one is in the view\n\t\t\t\t\t(c - 1 >= 0 && messages[c].offsetTop >= chatViewTop && messages[c - 1].offsetTop + messages[c - 1].offsetHeight)\n\t\t\t\t) {\n\t\t\t\t\ttopMessageIndex = c;\n\t\t\t\t\t// We should break as soon as we find it\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Otherwise we traverse up the chat log\n\t\telse {\n\t\t\tfor (; c >= 0; c--) {\n\t\t\t\tif (\n\t\t\t\t\t// If this message is at/on the scroll top\n\t\t\t\t\t(messages[c].offsetTop <= chatViewTop && messages[c].offsetTop + messages[c].offsetHeight >= chatViewTop) ||\n\t\t\t\t\t// If the previous message is above the view, and this one is in the view\n\t\t\t\t\t(c - 1 >= 0 && messages[c].offsetTop >= chatViewTop && messages[c - 1].offsetTop + messages[c - 1].offsetHeight)\n\t\t\t\t) {\n\t\t\t\t\ttopMessageIndex = c;\n\t\t\t\t\t// We should break as soon as we find it\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// If we found nothing\n\t\tif (topMessageIndex < 0) {\n\t\t\treturn Promise.resolve();\n\t\t}\n\n\t\t// Check if we should load more messages\n\t\tif (topMessageIndex < (CONFIG.ChatMessage.batchSize / 4) && messages.length < this.collection.size) {\n\t\t\t// Add Messages\n\t\t\treturn this._renderBatch(this.element, CONFIG.ChatMessage.batchSize);\n\t\t}\n\t\t// If we don't want to load more, check if we should delete some\n\t\telse if (topMessageIndex > maxMessageCount) {\n\t\t\tconst count = topMessageIndex - (maxMessageCount - 1);\n\t\t\t// Set the Last ID for batch rendering\n\t\t\tthis._lastId = messages[count].dataset.messageId;\n\t\t\t// Remove the messages\n\t\t\tmessages.slice(0, count).remove();\n\t\t}\n\t\treturn Promise.resolve();\n\t}\n\n\tprivate static _lastFrame = 0;\n\tprivate static _displayMessageCounts(time: number) {\n\t\tif (ChatHistoryOptimizer._lastFrame + 500 < time) {\n\t\t\tChatHistoryOptimizer._lastFrame = time;\n\t\t\t$('.dfce-chat-count').each(function (_, element: HTMLElement) {\n\t\t\t\tconst msgCount = $(element).siblings('#chat-log').find('li.chat-message').length;\n\t\t\t\telement.innerText = `${msgCount} / ${ui.chat.collection.size}`;\n\t\t\t});\n\t\t}\n\t\trequestAnimationFrame(ChatHistoryOptimizer._displayMessageCounts);\n\t}\n}","import { ChatMessageData } from \"@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs\";\nimport libWrapperShared from \"../../../common/libWrapperShared\";\nimport SETTINGS from \"../../../common/Settings\";\nimport ChatHistoryOptimizer from \"./ChatHistoryOptimizer\";\n\ndeclare class ChatLogExt extends ChatLog {\n\t_scrollToBottomButton: JQuery<HTMLElement>;\n}\n\nexport default class ScrollManage {\n\tprivate static readonly PREF_ENABLED = 'scroll-manage-enabled';\n\tprivate static readonly PREF_SCROLL_IF_YOU = 'scroll-manage-scroll-if-you';\n\tprivate static readonly ScrollThreshold = 50;\n\t// private static _scrollToBottomButton: JQuery<HTMLElement>;\n\tprivate static _deleteMessageRegistrationID: number | null = null;\n\n\n\tstatic get enabled(): boolean { return SETTINGS.get(this.PREF_ENABLED); }\n\tstatic get scrollToBottomIfYouSendMessage(): boolean { return SETTINGS.get(this.PREF_SCROLL_IF_YOU); }\n\n\tstatic init() {\n\t\tHooks.on('renderChatLog', this._renderChatLog.bind(this));\n\n\t\tSETTINGS.register(this.PREF_ENABLED, {\n\t\t\tname: 'DF_CHAT_SCROLL.EnableName',\n\t\t\thint: 'DF_CHAT_SCROLL.EnableHint',\n\t\t\tscope: 'world',\n\t\t\tconfig: true,\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tonChange: (newValue) => {\n\t\t\t\tif (newValue) this.register();\n\t\t\t\telse this.unregister();\n\t\t\t}\n\t\t});\n\t\tSETTINGS.register(this.PREF_SCROLL_IF_YOU, {\n\t\t\tname: 'DF_CHAT_SCROLL.ScrollIfYouName',\n\t\t\thint: 'DF_CHAT_SCROLL.ScrollIfYouHint',\n\t\t\tscope: 'world',\n\t\t\tconfig: true,\n\t\t\ttype: Boolean,\n\t\t\tdefault: true\n\t\t});\n\n\t\tChatHistoryOptimizer.init();\n\t}\n\n\tstatic ready() {\n\t\tif (this.enabled)\n\t\t\tthis.register();\n\t}\n\n\tprivate static register() {\n\t\tlibWrapper.register(SETTINGS.MOD_NAME, 'ChatLog.prototype.postOne', this._ChatLog_postOne, 'OVERRIDE');\n\t\tlibWrapper.register(SETTINGS.MOD_NAME, 'ChatLog.prototype.scrollBottom', this._ChatLog_scrollBottom, 'OVERRIDE');\n\t\tthis._deleteMessageRegistrationID = libWrapperShared.register('ChatLog.prototype.deleteMessage', this._ChatLog_deleteMessage);\n\t}\n\tprivate static unregister() {\n\t\tlibWrapper.unregister(SETTINGS.MOD_NAME, 'ChatLog.prototype.postOne', false);\n\t\tlibWrapper.unregister(SETTINGS.MOD_NAME, 'ChatLog.prototype.scrollBottom', false);\n\t\tlibWrapperShared.unregister('ChatLog.prototype.deleteMessage', this._deleteMessageRegistrationID);\n\t}\n\n\tprivate static _renderChatLog(app: ChatLogExt, html: JQuery<HTMLElement>) {\n\t\tapp._scrollToBottomButton = $(`<div id=\"scrollToBottom\" style=\"display:none\">\n\t<span>${'DF_CHAT_SCROLL.NewMessage'.localize()}</span> ${'DF_CHAT_SCROLL.ScrollButton'.localize()}\n</div>`);\n\t\tapp._scrollToBottomButton.on('click', () => {\n\t\t\tconst el = app.element;\n\t\t\tconst log = el.length ? el[0].querySelector(\"#chat-log\") : null;\n\t\t\tif (log) {\n\t\t\t\tlog.scrollTo({ behavior: \"smooth\", top: log.scrollHeight });\n\t\t\t}\n\t\t});\n\t\thtml.find('div#chat-controls').before(app._scrollToBottomButton);\n\n\t\thtml.find('ol#chat-log').on('scroll', (event) => {\n\t\t\tif (!app._scrollToBottomButton) return;\n\t\t\tconst element = <HTMLOListElement>event.currentTarget;\n\t\t\t// Ignore events when the scroll height is too small to matter\n\t\t\tif (element.clientHeight > element.scrollHeight - this.ScrollThreshold) return;\n\t\t\tif (element.scrollTop < (element.scrollHeight - element.clientHeight) - this.ScrollThreshold)\n\t\t\t\tapp._scrollToBottomButton.show();\n\t\t\telse {\n\t\t\t\tapp._scrollToBottomButton.hide();\n\t\t\t\tapp._scrollToBottomButton.removeClass('new');\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate static _ChatLog_scrollBottom(this: ChatLogExt) {\n\t\tconst el = this.element;\n\t\tconst log = el.length ? el[0].querySelector(\"#chat-log\") : null;\n\t\t// If we are already at the bottom, perform the scroll\n\t\tif (this._scrollToBottomButton.is(':hidden'))\n\t\t\tsetTimeout(() => log.scrollTo({ behavior: 'smooth', top: log.scrollHeight }), 100);\n\t\t// Otherwise do not scroll, but do trigger a scroll event.\n\t\t// Some modules might use this function after manually adding message content to the ChatLog\n\t\telse $('#chat #chat-log').trigger('scroll');\n\t}\n\n\tprivate static async _ChatLog_postOne(this: ChatLogExt, message: ChatMessageData & ChatMessage, notify = false) {\n\t\tif (!message.visible) return;\n\n\t\t// Track internal flags\n\t\tif (!this._lastId) this._lastId = message.id; // Ensure that new messages don't result in batched scrolling\n\t\tif ((message.whisper || []).includes(game.user.id) && !message.isRoll) {\n\t\t\tthis._lastWhisper = message;\n\t\t}\n\n\t\t// Render the message to the log\n\t\tconst element = this.element.find(\"#chat-log\");\n\t\tconst atBottom = element[0].scrollTop >= ((element[0].scrollHeight - element[0].clientHeight) - ScrollManage.ScrollThreshold);\n\t\tconst html = await (<any>message).getHTML();\n\t\telement.append(html);\n\t\tif (atBottom || (ScrollManage.scrollToBottomIfYouSendMessage && message.isAuthor))\n\t\t\telement[0].scrollTo({ top: element[0].scrollHeight, behavior: 'smooth' });\n\t\t// this.scrollBottom();\n\t\telse {\n\t\t\tthis._scrollToBottomButton.addClass('new');\n\t\t}\n\n\t\t// Post notification\n\t\tif (notify) this.notify(message);\n\n\t\t// Update popout tab\n\t\tif (this._popout) await (<any>this._popout).postOne(message, false);\n\t\tif (this.popOut) this.setPosition();\n\t}\n\n\tprivate static _ChatLog_deleteMessage(this: ChatLogExt, wrapped: (...args: any) => unknown, messageId: string, { deleteAll = false }: { deleteAll?: boolean } = {}): unknown {\n\t\tconst result = wrapped(messageId, { deleteAll });\n\t\t// Ignore singular message deletions, only react to a Delete All event.\n\t\t// Also ignore the deletion if the scroll-to-bottom element is already hidden\n\t\tif (!deleteAll || this._scrollToBottomButton.is(':hidden')) return result;\n\t\tthis._scrollToBottomButton.hide();\n\t\tthis._scrollToBottomButton.removeClass('new');\n\t\treturn result;\n\t}\n}","import SETTINGS from \"../../../common/Settings\";\n\nexport default class SendButton {\n\tprivate static readonly PREF_ENABLED = 'SendButton.Enabled';\n\tstatic init() {\n\t\tSETTINGS.register(this.PREF_ENABLED, {\n\t\t\tname: 'DF_CHAT_SEND_BUTTON.EnabledName'.localize(),\n\t\t\thint: 'DF_CHAT_SEND_BUTTON.EnabledHint'.localize(),\n\t\t\tconfig: true,\n\t\t\tscope: 'client',\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t\tonChange: (isActive) => {\n\t\t\t\tif (isActive) {\n\t\t\t\t\tthis._renderChatLog(ui.chat, $('#sidebar #chat'));\n\t\t\t\t\tconst popout = $('#chat-popout');\n\t\t\t\t\tif (popout.length > 0)\n\t\t\t\t\t\tthis._renderChatLog(ui.chat, popout);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t$('.dfce-send-btn').remove();\n\t\t\t\t\t$<HTMLTextAreaElement>('#chat-message').each((_a, textarea) => {\n\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\t$(textarea).off('input', textarea.dfce_handler);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tHooks.on('renderChatLog', this._renderChatLog.bind(this));\n\t}\n\n\tprivate static _renderChatLog(app: ChatLog, html: JQuery<HTMLElement>) {\n\t\tif (!SETTINGS.get<boolean>(this.PREF_ENABLED)) return;\n\t\tconst sendButton = $('<button class=\"dfce-send-btn\"><i class=\"fas fa-paper-plane\"></i></button>');\n\t\tsendButton.attr('title', 'DF_CHAT_SEND_BUTTON.ButtonTitle'.localize());\n\t\thtml.find('#chat-form').append(sendButton);\n\n\t\tconst textarea = html.find<HTMLTextAreaElement>('#chat-message');\n\t\tsendButton.prop('disabled', textarea[0].textLength <= 0 || textarea[0].value.trim().length <= 0);\n\n\t\tsendButton.on('click', async event => {\n\t\t\tevent.preventDefault();\n\t\t\t// @ts-expect-error\n\t\t\tawait ui.chat._onChatKeyDown(<any>{\n\t\t\t\tcode: 'Enter',\n\t\t\t\tcurrentTarget: textarea[0],\n\t\t\t\toriginalEvent: <any>{\n\t\t\t\t\tisComposing: false\n\t\t\t\t},\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-empty-function\n\t\t\t\tpreventDefault: () => { }\n\t\t\t});\n\t\t\tsetTimeout(() => textarea.trigger('input'), 100);\n\t\t});\n\n\t\tconst handler = (event: JQuery.TriggeredEvent<HTMLTextAreaElement, undefined, HTMLTextAreaElement, HTMLTextAreaElement>) => {\n\t\t\tconst element = (event.currentTarget as HTMLTextAreaElement);\n\t\t\tsendButton.prop('disabled', element.textLength <= 0 || element.value.trim().length <= 0);\n\t\t};\n\t\t// @ts-expect-error\n\t\ttextarea[0].dfce_handler = handler;\n\t\ttextarea.on('input', handler);\n\t\ttextarea.on('change', handler);\n\t}\n}","import { ChatMessageData } from \"@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs\";\nimport SETTINGS from \"../../../common/Settings\";\n\n\nconst TEMPLATE = \"$0: $1 (+$2&nbsp;more)\";\nconst LENGTH_ADJUST = '&nbsp;'.length - 1;\n\n\nexport default class WhisperTruncation {\n\n\tprivate static readonly PREF_ENABLED = 'whisper-trunc_enabled';\n\tprivate static readonly PREF_CHAR_LIMIT = 'whisper-trunc_char-limit';\n\n\tstatic init() {\n\t\tHooks.on('renderChatMessage', this._messageRender.bind(this));\n\t\tSETTINGS.register(this.PREF_ENABLED, {\n\t\t\tname: 'DF_CHAT_WHISPER_TRUNC.SettingEnabledName',\n\t\t\thint: 'DF_CHAT_WHISPER_TRUNC.SettingEnabledHint',\n\t\t\tconfig: true,\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t\tscope: 'world',\n\t\t\tonChange: async () => {\n\t\t\t\t(<any>ui.chat)._state = 0;\n\t\t\t\t(<any>ui.chat)._lastId = null;\n\t\t\t\tawait ui.chat.render(true);\n\t\t\t}\n\t\t});\n\t\tSETTINGS.register(this.PREF_CHAR_LIMIT, {\n\t\t\tname: 'DF_CHAT_WHISPER_TRUNC.SettingCharLimitName',\n\t\t\thint: 'DF_CHAT_WHISPER_TRUNC.SettingCharLimitHint',\n\t\t\tconfig: true,\n\t\t\ttype: Number,\n\t\t\tdefault: 50,\n\t\t\tscope: 'world',\n\t\t\tonChange: async () => {\n\t\t\t\t(<any>ui.chat)._state = 0;\n\t\t\t\t(<any>ui.chat)._lastId = null;\n\t\t\t\tawait ui.chat.render(true);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate static _messageRender(message: ChatMessageData, html: JQuery<HTMLElement>, _cmd: ChatMessageData) {\n\t\t// ignore regular messages, or whispers with only 1 recipient\n\t\tif (!SETTINGS.get(this.PREF_ENABLED) || !(message.whisper) || message.whisper.length <= 1) return;\n\t\tconst users = message.whisper.map(x => game.users.get(x));\n\t\tlet accum = users[0].name;\n\t\tlet title = this._formatTitle(accum, users.length - 1);\n\t\tlet c = 1;\n\t\tconst CHAR_LIMIT = SETTINGS.get<number>(this.PREF_CHAR_LIMIT);\n\t\tfor (; c < users.length; c++) {\n\t\t\t// Append name to names string\n\t\t\tconst tmpNames = accum + ', ' + users[c].name;\n\t\t\t// Generate a temp title\n\t\t\tconst tmpTitle = this._formatTitle(tmpNames, users.length - c - 1);\n\t\t\t// If the potential title is too large, break so we can use the previous iteration's results\n\t\t\tif (tmpTitle.length - LENGTH_ADJUST > CHAR_LIMIT) break;\n\t\t\t// Set the accum and title to the newly generated values\n\t\t\taccum = tmpNames;\n\t\t\ttitle = tmpTitle;\n\t\t}\n\t\t// If we never ran out of room, exit\n\t\tif (c === users.length) return;\n\t\t// Update the HTML\n\t\tconst newHeader = `<span class=\"whisper-to\" title=\"${users.slice(c).map(x => x.name).join(', ')}\">${title}</span>`;\n\t\thtml.find('span.whisper-to').replaceWith(newHeader);\n\t}\n\n\tprivate static _formatTitle(names: string, count: number): string {\n\t\treturn count > 0\n\t\t\t? TEMPLATE\n\t\t\t\t.replace('$0', 'CHAT.To'.localize())\n\t\t\t\t.replace('$1', names)\n\t\t\t\t.replace('$2', count.toString())\n\t\t\t: names;\n\t}\n}","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import * as DFChatArchive from \"./archive/df-chat-archive\";\nimport DFChatEdit from \"./edit/df-chat-edit\";\nimport * as DFAdventureLog from \"./logger/df-adventure-log\";\nimport DFAdventureLogProcessor from \"./logger/DFAdventureLogProcessor\";\nimport ChatMerge from \"./merge/chat-merge\";\nimport ChatRollPrivacy from \"./privacy/df-chat-privacy\";\nimport ScrollManage from \"./scroll-manage/scroll-manage\";\nimport SETTINGS from \"../../common/Settings\";\nimport WhisperTruncation from \"./whisper-trunc/whisper-trunc\";\nimport PlayerColor from './player-color/PlayerColor';\nimport SendButton from \"./send/send-button\";\nimport FontSizePatch from \"./font-size/font-size\";\nimport ChatTime from \"./chat-time/chat-time\";\nSETTINGS.init('df-chat-enhance');\n\ndeclare global {\n\tinterface Application {\n\t\t_recalculateDimensions(): void;\n\t}\n}\n\n(<any>Application.prototype)._recalculateDimensions = function () {\n\tthis.element[0].style.height = '';\n\tthis.element[0].style.width = '';\n\tthis.setPosition({});\n};\n\nHooks.once('setup', function () {\n\tChatRollPrivacy.setup();\n});\n\nHooks.once('init', function () {\n\t/**\n\t * Order here matters! The archive adds a button to the\n\t * chat window, while the privacy changes those buttons\n\t * from <a> tags to <button> tags if enabled.\n\t */\n\tDFChatArchive.init();\n\tChatRollPrivacy.init();\n\tDFAdventureLog.init();\n\tChatMerge.init();\n\tScrollManage.init();\n\tWhisperTruncation.init();\n\tPlayerColor.init();\n\tSendButton.init();\n\tFontSizePatch.init();\n\tChatTime.init();\n\n\tlibWrapper.register(SETTINGS.MOD_NAME, 'ChatLog.prototype._getEntryContextOptions', function (wrapped: (...args: any) => ContextMenu.Item[], ...args: any) {\n\t\tconst options = wrapped(...args);\n\t\tDFChatEdit.appendChatContextMenuOptions(options);\n\t\tDFAdventureLogProcessor.appendChatContextMenuOptions(options);\n\t\treturn options;\n\t}, 'WRAPPER');\n});\n\nHooks.once('ready', function () {\n\tif (!game.modules.get('lib-wrapper')?.active) {\n\t\tconsole.error('Missing libWrapper module dependency');\n\t\tif (game.user.isGM)\n\t\t\tui.notifications.error('DF_CHAT_LOG.Error.LibWrapperMissing'.localize());\n\t}\n\tDFAdventureLog.ready();\n\tDFChatEdit.ready();\n\tChatMerge.ready();\n\tScrollManage.ready();\n\tChatTime.ready();\n});\n"],"names":["SETTINGS","static","moduleName","this","MOD_NAME","String","prototype","localize","game","i18n","valueOf","key","config","settings","register","registerMenu","get","value","set","default","Object","Registration","nextId","wrappers","Map","handler","context","wrapped","args","current","wrapper","values","next","call","libWrapperShared","target","registration","registrations","libWrapper","id","delete","size","unregister","UTIL","Dialog","confirm","title","content","defaultYes","window","location","reload","ui","chat","_lastId","_state","Application","RENDER_STATES","NONE","render","ArchiveFolderMenu","FormApplication","folder","DFChatArchive","PREF_FOLDER","source","PREF_FOLDER_SOURCE","defaultOptions","mergeObject","width","height","resizable","minimizable","template","submitOnClose","submitOnChange","closeOnSubmit","getData","_options","path","async","data","html","super","_renderInner","input","find","on","event","preventDefault","fp","FilePicker","type","field","callback","activeSource","button","currentTarget","browse","DATA_FOLDER","listener","_updateListener","PREF_LOGS","scope","onChange","PREF_CID","Number","PREF_FOLDER_MENU","label","hint","restricted","world","createArchiveFolderIfMissing","catch","_","createDirectory","Error","getLogs","x","name","chats","visible","folderPath","safeName","replace","fileName","encodeURI","file","File","JSON","stringify","response","upload","console","error","filepath","filename","newId","entry","_generateChatArchiveFile","logs","push","archive","fetch","json","ok","newChatData","toString","idx","findIndex","Promise","all","map","entryIdx","splice","DFChatArchiveManager","options","messages","user","isGM","filter","sort","a","b","localeCompare","reverseSort","PREF_REVERSE_SORT","reverse","_subscribeView","element","parseInt","$","attr","isNaN","notifications","chatViewers","has","bringToTop","view","_subscribeDelete","yes","activateListeners","_archiveChanged","bind","length","hide","each","i","info","asc","dsc","show","close","archiveContainer","empty","append","children","DFChatArchiveNew","PREF_DELETE","Boolean","shouldDelete","_event","formData","warn","collection","fromDate","Date","from","getTime","toDate","to","timestamp","e","flush","then","prop","_recalculateDimensions","PREF_HIDE_EXPORT","DFChatArchiveViewer","constructor","onCloseCallBack","classes","logId","codeUnits","Uint16Array","charCodeAt","charCodes","Uint8Array","buffer","result","byteLength","fromCharCode","checked","setTimeout","dialog","buttons","save","icon","val","clone","addClass","print","remove","removeClass","renderTemplate","archives","cancel","merge","currentChats","sourceChats","mergedChats","concat","anchor","document","createElement","download","href","encodeURIComponent","click","log","messageHtml","userId","CONST","CHAT_MESSAGE_TYPES","WHISPER","whisper","some","deletionList","deleteButton","chatMessage","ChatMessage","getHTML","parentElement","buttonIcon","hasClass","err","prepend","message","includes","_id","init","archiveNew","archiveManager","newValue","Hooks","chatLog","archiveButton","archiveManagerHtml","RENDERED","RENDERING","app","focus","ChatTime","enabled","PREF_ENABLED","simpleCalendarActive","modules","active","permanent","PREF_FORMAT","chatData","createOptions","flags","FLAG_CHAT_TIME","time","worldTime","_data","simpleTimestamp","getFlag","undefined","timeElement","simpleTimeElement","SimpleCalendar","api","formatDateTime","timestampToDate","after","DFChatEditor","editable","popOut","types","keys","CONFIG","Actor","typeLabels","actors","scenes","viewed","tokens","contents","actor","selected","speaker","token","players","users","actorGroups","messageText","PREF_MARKDOWN","processMarkdown","search","startsWith","substring","_getSpeakerFromUser","getSpeaker","alias","update","chatEditor","originalMessage","marked","parse","headerIds","breaks","trimEnd","substr","endsWith","newLine","test","PREF_EDIT_ALLOWED","PREF_GM_ALL","PREF_IGNORE_HTML","DFChatEdit","PREF_SHOW_EDITED","code","ctrlKey","editChatMessage","trim","split","trimStart","_sentMessages","unshift","condition","header","processChatMessage","_render","str","doc","DOMParser","parseFromString","Array","body","childNodes","node","HTMLElement","classList","contains","HTMLBRElement","nodeType","isRoll","isHTML","FontSizePatch","PREF_SIZE","range","min","max","step","newSize","updateFontSize","querySelector","style","setProperty","DFAdventureLogConfig","PREF_JOURNAL","PREF_JOURNAL_GM","PREF_CONFIG","journal","pages","y","selectedLog","selectedGMLog","logJournals","logJournalPages","gmlogJournals","gmlogJournalPages","fillPageList","journalId","page","pageElement","logJournal","gmlogJournal","clear","gmClear","initializeJournal","isGMOnly","isPlayerLog","text","whitespace","index","c","every","DFAdventureLogProcessor","PREF_ENABLE","gmOnly","PREF_GMONLY","commandProcessor","logCommand","deregisterCommand","registerCommand","PREF_GMONLY_WHISPER","PREF_USE_TIME","PREF_MESSAGES","PREF_SORTDESC","resortLog","PREF_DISABLE_FORMATTING","PREF_DISABLE_AUTHOR","PREF_SIMPLE_CALENDAR","logConfig","chatCommands","plogCommand","gmlogCommand","createCommandFromData","commandKey","invokeOnCommand","_cl","msg","_cd","shouldDisplayToChat","iconClass","description","useTime","stamp","date","toLocaleString","gmLog","preventPostToChat","prompt","messageData","flavor","OOC","line","disableFormatting","disableAuthor","toLowerCase","slice","_getTimestamp","PREF_PLAYER_LOG_JOURNAL","section","join","rollType","create","descending","journalAll","journalGM","journalSort","article","postToChat","pevent","gmevent","quote","pquote","gmquote","AdventureLog","ready","_app","Handlebars","compile","journals","documents","testUserPermission","DOCUMENT_PERMISSION_LEVELS","OBSERVER","journalSelection","allowProtoMethodsByDefault","allowProtoPropertiesByDefault","parent","before","object","setFlag","migrateDataV9toV10","checkJournal","migrateJournalV9toV10","unsetFlag","ChatMerge","_enabled","_epoch","PREF_EPOCH","_allowRolls","PREF_ALLOW_ROLLS","_separateWithBorder","PREF_SEPARATE","_showHover","PREF_HOVER","_showHeader","PREF_SHOW_HEADER","_processAllMessage","PREF_SPLIT_SPEAKER","choices","none","rolls","removeProperty","_deleteMessage","_renderChatMessage","messageId","deleteAll","nextElementSibling","add","previousElementSibling","hasAttribute","borderColor","_styleChatMessages","getAttribute","_cmd","partnerElem","last","partner","previous","splitSpeaker","userCompare","currData","prevData","_inTimeFrame","curr","currElem","prev","prevElem","exec","dataset","_isValidMessage","PlayerColor","PREF_TINT_BG","PREF_BORDER_STYLE","mine","color","FLAG_CHAT_COLOR","chatField","chatPicker","setPosition","chatColor","borderColour","backgroundColor","backgroundImage","backgroundRepeat","backgroundBlendMode","ICONS_FOR_KNOWN_ROLL_TYPES","publicroll","gmroll","blindroll","selfroll","ChatRollPrivacy","keybindings","modifiers","KeyboardManager","MODIFIER_KEYS","ALT","namespace","onDown","trigger","_handleChatLogRendering","count","modes","rollModes","iconKeys","rt","rollMode","colour","calcColour","buttonHtml","first","ChatHistoryOptimizer","PREF_HISTORY_SIZE","batchSize","_ChatLog_onScrollLog","rendered","resolve","maxMessageCount","topMessageIndex","pct","scrollTop","scrollHeight","chatViewTop","offsetTop","Math","trunc","offsetHeight","_renderBatch","_lastFrame","msgCount","siblings","innerText","requestAnimationFrame","_displayMessageCounts","ScrollManage","scrollToBottomIfYouSendMessage","PREF_SCROLL_IF_YOU","_renderChatLog","_ChatLog_postOne","_ChatLog_scrollBottom","_deleteMessageRegistrationID","_ChatLog_deleteMessage","_scrollToBottomButton","el","scrollTo","behavior","top","clientHeight","ScrollThreshold","is","notify","_lastWhisper","atBottom","isAuthor","_popout","postOne","SendButton","isActive","popout","_a","textarea","off","dfce_handler","sendButton","textLength","_onChatKeyDown","originalEvent","isComposing","LENGTH_ADJUST","WhisperTruncation","_messageRender","PREF_CHAR_LIMIT","accum","_formatTitle","CHAR_LIMIT","tmpNames","tmpTitle","newHeader","replaceWith","names","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","d","definition","o","defineProperty","enumerable","obj","hasOwnProperty","r","Symbol","toStringTag","once"],"sourceRoot":""}