diff --git a/public/common/bus.js b/public/common/bus.js index 057c20883..7118db138 100644 --- a/public/common/bus.js +++ b/public/common/bus.js @@ -8,4 +8,6 @@ export const SEARCH_STRING_CHANGED = "searchStringChanged"; export const PLAYER_MODAL = "playerModal"; -export const SET_LOADING = 'setLoading'; \ No newline at end of file +export const SET_LOADING = 'setLoading'; + +export const OPEN_VIEW_FILES_DIALOG = "openViewFiles"; diff --git a/public/common/components/FileListContextMenu.vue b/public/common/components/FileListContextMenu.vue new file mode 100644 index 000000000..b188bf8b9 --- /dev/null +++ b/public/common/components/FileListContextMenu.vue @@ -0,0 +1,93 @@ + + + diff --git a/public/common/components/FileListModal.vue b/public/common/components/FileListModal.vue index 913188aa6..51473ec9e 100644 --- a/public/common/components/FileListModal.vue +++ b/public/common/components/FileListModal.vue @@ -132,19 +132,19 @@ import bus, { OPEN_VIEW_FILES_DIALOG, PLAYER_MODAL, -} from "./bus/bus"; +} from "../bus"; import axios from "axios"; import { formatSize, hasLength, -} from "./utils"; -import { getHumanReadableDate } from "@/date.js"; + FIRST_PAGE, PAGE_SIZE_SMALL, +} from "../utils"; +import { getHumanReadableDate } from "../date"; import debounce from "lodash/debounce"; -import CollapsedSearch from "@/CollapsedSearch.vue"; +import CollapsedSearch from "./CollapsedSearch.vue"; import Mark from "mark.js"; -import {firstPage, pageSize} from "@/mixins/pageableModalMixin.js"; -import {getStoredFileListMode, setStoredFileListMode} from "@/store/localStore.js"; -import FileListContextMenu from "@/FileListContextMenu.vue"; +import {getStoredFileListMode, setStoredFileListMode} from "../localStore.js"; +import FileListContextMenu from "./FileListContextMenu.vue"; export default { data () { @@ -152,7 +152,7 @@ export default { show: false, itemsDto: dtoFactory(), loading: false, - page: firstPage, + page: FIRST_PAGE, dataLoaded: false, messageIdToDetachFiles: null, @@ -169,11 +169,11 @@ export default { }, computed: { pagesCount() { - const count = Math.ceil(this.itemsDto.count / pageSize); + const count = Math.ceil(this.itemsDto.count / PAGE_SIZE_SMALL); return count; }, shouldShowPagination() { - return this.itemsDto != null && this.itemsDto.items && this.itemsDto.count > pageSize + return this.itemsDto != null && this.itemsDto.items && this.itemsDto.count > PAGE_SIZE_SMALL }, fileModeIcon() { @@ -254,7 +254,7 @@ export default { this.clearOnClose(); }, reset() { - this.page = firstPage; + this.page = FIRST_PAGE; this.itemsDto = dtoFactory(); this.dataLoaded = false; this.clearOnReset(); @@ -290,7 +290,7 @@ export default { return axios.get(`/api/storage/${this.chatId}`, { params: { page: this.translatePage(), - size: pageSize, + size: PAGE_SIZE_SMALL, fileItemUuid : this.fileItemUuid ? this.fileItemUuid : '', searchString: this.searchString }, @@ -301,7 +301,7 @@ export default { return } - this.page = firstPage; + this.page = FIRST_PAGE; this.updateItems(); }, transformItems(items) { diff --git a/public/common/components/MessageItem.vue b/public/common/components/MessageItem.vue index e2060690a..dae6dad7d 100644 --- a/public/common/components/MessageItem.vue +++ b/public/common/components/MessageItem.vue @@ -38,8 +38,11 @@ import { embed_message_reply, embed_message_resend, - getHumanReadableDate, getLoginColoredStyle, hasLength, + getLoginColoredStyle, hasLength, } from "#root/common/utils"; + import { + getHumanReadableDate, + } from "#root/common/date"; import "#root/common/styles/messageBody.styl"; import "#root/common/styles/messageWrapper.styl"; import "#root/common/styles/itemAvatar.styl"; diff --git a/public/common/date.js b/public/common/date.js new file mode 100644 index 000000000..85e771c30 --- /dev/null +++ b/public/common/date.js @@ -0,0 +1,15 @@ +import {differenceInDays, format, parseISO} from "date-fns"; +import {enUS} from "date-fns/locale"; + +export const getHumanReadableDate = (timestamp) => { + const parsedDate = parseISO(timestamp); + let formatString = 'HH:mm:ss'; + if (differenceInDays(new Date(), parsedDate) >= 1) { + formatString = formatString + ', d MMM yyyy'; + } + + const localeObj = {}; + localeObj.locale = enUS; + + return `${format(parsedDate, formatString, localeObj)}` +} diff --git a/public/common/localStore.js b/public/common/localStore.js new file mode 100644 index 000000000..777264ef4 --- /dev/null +++ b/public/common/localStore.js @@ -0,0 +1,16 @@ +export const KEY_FILE_LIST_MODE = 'fileListMode'; + +export const getStoredFileListMode = () => { + let v = JSON.parse(localStorage.getItem(KEY_FILE_LIST_MODE)); + if (v === null) { + console.log("Resetting fileListMode to default"); + const defaultFileListMode = !isMobileBrowser(); + setStoredFileListMode(defaultFileListMode); + v = JSON.parse(localStorage.getItem(KEY_FILE_LIST_MODE)); + } + return v; +} + +export const setStoredFileListMode = (v) => { + localStorage.setItem(KEY_FILE_LIST_MODE, JSON.stringify(v)); +} diff --git a/public/common/mixins/contextMenuMixin.js b/public/common/mixins/contextMenuMixin.js new file mode 100644 index 000000000..f333c446c --- /dev/null +++ b/public/common/mixins/contextMenuMixin.js @@ -0,0 +1,63 @@ +export default () => { + return { + data(){ + return { + showContextMenu: false, + menuableItem: null, + contextMenuX: 0, + contextMenuY: 0, + } + }, + methods: { + setPosition() { + const element = document.querySelector("." + this.className() + " .v-overlay__content"); + if (element) { + element.style.position = "absolute"; + element.style.top = this.contextMenuY + "px"; + element.style.left = this.contextMenuX + "px"; + + const bottom = Number(getComputedStyle(element).bottom.replace("px", '')); + if (bottom < 0) { + const newTop = this.contextMenuY + bottom - 8; + element.style.top = newTop + "px"; + } + + const width = Number(getComputedStyle(element).width.replace("px", '')); + if (width < 260) { + const delta = Math.abs(260 - width); + const newLeft = this.contextMenuX - delta - 8; + element.style.left = newLeft + "px"; + } + } + }, + onShowContextMenuBase(e, menuableItem) { + e.preventDefault(); + + this.contextMenuX = e.clientX; + this.contextMenuY = e.clientY; + + this.menuableItem = menuableItem; + + if (!this.getContextMenuItems().length) { + console.log("No items in the context menu"); + return; + } + + this.$nextTick(() => { + this.showContextMenu = true; + }).then(() => { + this.setPosition() + }) + }, + onCloseContextMenuBase() { + this.showContextMenu = false; + this.menuableItem = null; + }, + onUpdate(v) { + if (!v) { + this.onCloseContextMenu(); + } + }, + } + } +} diff --git a/public/common/utils.js b/public/common/utils.js index 5d0635dcf..cff563565 100644 --- a/public/common/utils.js +++ b/public/common/utils.js @@ -1,18 +1,8 @@ -import { format, parseISO, differenceInDays } from 'date-fns'; import {chat, messageIdHashPrefix} from "./router/routes.js"; import bus, {PLAYER_MODAL} from "./bus.js"; import axios from "axios"; import he from "he"; -export const getHumanReadableDate = (timestamp) => { - const parsedDate = parseISO(timestamp); - let formatString = 'HH:mm:ss'; - if (differenceInDays(new Date(), parsedDate) >= 1) { - formatString = formatString + ', d MMM yyyy'; - } - return `${format(parsedDate, formatString)}` -} - export const hasLength = (str) => { if (!str) { return false @@ -57,7 +47,9 @@ export const findIndexNonStrictly = (array, element) => { return array.findIndex(value => value.id == element.id); }; +export const FIRST_PAGE = 1; export const PAGE_SIZE = 40; +export const PAGE_SIZE_SMALL = 20; export const SEARCH_MODE_POSTS = "qp" @@ -245,3 +237,17 @@ export const unescapeHtml = (text) => { } return he.decode(text); } + +export const formatSize = (size) => { + const operableSize = Math.abs(size); + if (operableSize > 1024 * 1024 * 1024 * 1024) { + return (size / 1024 / 1024 / 1024 / 1024).toFixed(2) + ' TB' + } else if (operableSize > 1024 * 1024 * 1024) { + return (size / 1024 / 1024 / 1024).toFixed(2) + ' GB' + } else if (operableSize > 1024 * 1024) { + return (size / 1024 / 1024).toFixed(2) + ' MB' + } else if (operableSize > 1024) { + return (size / 1024).toFixed(2) + ' KB' + } + return size.toString() + ' B' +}; diff --git a/public/pages/blog/BlogList.vue b/public/pages/blog/BlogList.vue index 166bb33a1..035a2462f 100644 --- a/public/pages/blog/BlogList.vue +++ b/public/pages/blog/BlogList.vue @@ -77,7 +77,10 @@