displaying "years" correcty in abyss for old items
This commit is contained in:
@@ -212,21 +212,21 @@
|
|||||||
function timeAgo(iso) {
|
function timeAgo(iso) {
|
||||||
const s = Math.floor((Date.now() - new Date(iso)) / 1000);
|
const s = Math.floor((Date.now() - new Date(iso)) / 1000);
|
||||||
const i = window.f0ckI18n || {};
|
const i = window.f0ckI18n || {};
|
||||||
const fmt = (tpl, n) => (tpl || '{n}').replace('{n}', n);
|
const fmt = (tpl, n, unit) => (tpl || `{n} ${unit}${n !== 1 ? 's' : ''}`).replace('{n}', n);
|
||||||
const ago = (t) => (i.ta_ago || '{t} ago').replace('{t}', t);
|
const ago = (t) => (i.ta_ago || '{t} ago').replace('{t}', t);
|
||||||
if (s < 60) return i.ta_just_now || i.just_now || 'just now';
|
if (s < 60) return i.ta_just_now || 'just now';
|
||||||
const m = Math.floor(s / 60);
|
const m = Math.floor(s / 60);
|
||||||
if (m < 60) return ago(fmt(m === 1 ? i.ta_minute : i.ta_minutes, m));
|
if (m < 60) return ago(fmt(m === 1 ? i.ta_minute : i.ta_minutes, m, 'minute'));
|
||||||
const h = Math.floor(s / 3600);
|
const h = Math.floor(s / 3600);
|
||||||
if (h < 24) return ago(fmt(h === 1 ? i.ta_hour : i.ta_hours, h));
|
if (h < 24) return ago(fmt(h === 1 ? i.ta_hour : i.ta_hours, h, 'hour'));
|
||||||
const d = Math.floor(s / 86400);
|
const d = Math.floor(s / 86400);
|
||||||
if (d < 7) return ago(fmt(d === 1 ? i.ta_day : i.ta_days, d));
|
if (d < 7) return ago(fmt(d === 1 ? i.ta_day : i.ta_days, d, 'day'));
|
||||||
const w = Math.floor(d / 7);
|
const w = Math.floor(d / 7);
|
||||||
if (d < 30) return ago(fmt(w === 1 ? i.ta_week : i.ta_weeks, w));
|
if (d < 30) return ago(fmt(w === 1 ? i.ta_week : i.ta_weeks, w, 'week'));
|
||||||
const mo = Math.floor(d / 30);
|
const mo = Math.floor(d / 30);
|
||||||
if (d < 365) return ago(fmt(mo === 1 ? i.ta_month : i.ta_months, mo));
|
if (d < 365) return ago(fmt(mo === 1 ? i.ta_month : i.ta_months, mo, 'month'));
|
||||||
const y = Math.floor(d / 365);
|
const y = Math.floor(d / 365);
|
||||||
return ago(fmt(y === 1 ? i.ta_year : i.ta_years, y));
|
return ago(fmt(y === 1 ? i.ta_year : i.ta_years, y, 'year'));
|
||||||
}
|
}
|
||||||
function hashId() {
|
function hashId() {
|
||||||
// Strip the leading '#' and allow numeric IDs or board/postid format
|
// Strip the leading '#' and allow numeric IDs or board/postid format
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import util from "util";
|
|||||||
import db from "./sql.mjs";
|
import db from "./sql.mjs";
|
||||||
|
|
||||||
import cfg from "./config.mjs";
|
import cfg from "./config.mjs";
|
||||||
|
import { createI18n } from "./i18n.mjs";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -43,11 +44,14 @@ export default new class {
|
|||||||
calcSpeed(b, s) {
|
calcSpeed(b, s) {
|
||||||
return (Math.round((b * 8 / s / 1e6) * 1e4) / 1e4);
|
return (Math.round((b * 8 / s / 1e6) * 1e4) / 1e4);
|
||||||
};
|
};
|
||||||
timeAgo(date) {
|
timeAgo(date, lang = 'en') {
|
||||||
|
const { t } = createI18n(lang);
|
||||||
const duration = getDuration(~~((new Date() - new Date(date)) / 1e3));
|
const duration = getDuration(~~((new Date() - new Date(date)) / 1e3));
|
||||||
if (!duration) return "just now";
|
if (!duration) return t('timeago.just_now');
|
||||||
const { interval, epoch } = duration;
|
const { interval, epoch } = duration;
|
||||||
return `${interval} ${epoch}${interval === 1 ? "" : "s"} ago`;
|
const unitKey = interval === 1 ? `timeago.${epoch}` : `timeago.${epoch}s`;
|
||||||
|
const timeStr = t(unitKey, { n: interval });
|
||||||
|
return t('timeago.ago', { t: timeStr });
|
||||||
};
|
};
|
||||||
md5(str) {
|
md5(str) {
|
||||||
return crypto.createHash('md5').update(str).digest("hex");
|
return crypto.createHash('md5').update(str).digest("hex");
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ export default {
|
|||||||
view_mode: fav ? 'favs' : 'uploads'
|
view_mode: fav ? 'favs' : 'uploads'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getf0ck: async ({ user: rawUser, tag: rawTag, hall: rawHall, mime: rawMime, itemid: rawItemid, mode, session, strict, exclude, user_id, fav, random, userHall: rawUserHall, userHallOwner: rawUserHallOwner } = {}) => {
|
getf0ck: async ({ user: rawUser, tag: rawTag, hall: rawHall, mime: rawMime, itemid: rawItemid, mode, session, strict, exclude, user_id, fav, random, userHall: rawUserHall, userHallOwner: rawUserHallOwner, lang } = {}) => {
|
||||||
const user = rawUser ? lib.escapeLike(decodeURI(rawUser)) : null;
|
const user = rawUser ? lib.escapeLike(decodeURI(rawUser)) : null;
|
||||||
const tag = lib.parseTag(rawTag ?? null);
|
const tag = lib.parseTag(rawTag ?? null);
|
||||||
let hall = rawHall ?? null;
|
let hall = rawHall ?? null;
|
||||||
@@ -614,7 +614,7 @@ export default {
|
|||||||
mime: actitem.mime,
|
mime: actitem.mime,
|
||||||
size: lib.formatSize(actitem.size),
|
size: lib.formatSize(actitem.size),
|
||||||
timestamp: {
|
timestamp: {
|
||||||
timeago: lib.timeAgo(new Date(actitem.stamp * 1e3).toISOString()),
|
timeago: lib.timeAgo(new Date(actitem.stamp * 1e3).toISOString(), lang),
|
||||||
timefull: new Date(actitem.stamp * 1e3).toISOString()
|
timefull: new Date(actitem.stamp * 1e3).toISOString()
|
||||||
},
|
},
|
||||||
favorites: favorites,
|
favorites: favorites,
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ export default (router, tpl) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
userData.timestamp = {
|
userData.timestamp = {
|
||||||
timeago: lib.timeAgo(userData.created_at),
|
timeago: lib.timeAgo(userData.created_at, req.lang),
|
||||||
timefull: userData.created_at
|
timefull: userData.created_at
|
||||||
};
|
};
|
||||||
userData.age_days = Math.floor((Date.now() - new Date(userData.created_at).getTime()) / 86400000);
|
userData.age_days = Math.floor((Date.now() - new Date(userData.created_at).getTime()) / 86400000);
|
||||||
@@ -228,7 +228,8 @@ export default (router, tpl) => {
|
|||||||
strict: !!(req.query?.strict || req.url.qs?.strict || req.session?.strict_mode),
|
strict: !!(req.query?.strict || req.url.qs?.strict || req.session?.strict_mode),
|
||||||
explicitStrict: !!(req.query?.strict || req.url.qs?.strict),
|
explicitStrict: !!(req.query?.strict || req.url.qs?.strict),
|
||||||
random: req.cookies.random_mode === '1',
|
random: req.cookies.random_mode === '1',
|
||||||
minXdScore: req.params.itemid ? 0 : (req.url.qs?.min_xd !== undefined ? +req.url.qs.min_xd : (req.session?.min_xd_score || 0))
|
minXdScore: req.params.itemid ? 0 : (req.url.qs?.min_xd !== undefined ? +req.url.qs.min_xd : (req.session?.min_xd_score || 0)),
|
||||||
|
lang: req.lang
|
||||||
});
|
});
|
||||||
console.log(`[DEBUG] Checking strict mode: query=${req.query?.strict}, session=${req.session?.strict_mode}, effective=${!!(req.query?.strict || req.url.qs?.strict || req.session?.strict_mode)}`);
|
console.log(`[DEBUG] Checking strict mode: query=${req.query?.strict}, session=${req.session?.strict_mode}, effective=${!!(req.query?.strict || req.url.qs?.strict || req.session?.strict_mode)}`);
|
||||||
console.log(`[${new Date().toISOString()}] [ROUTE] Data fetch complete in ${Date.now() - tRouteStart}ms`);
|
console.log(`[${new Date().toISOString()}] [ROUTE] Data fetch complete in ${Date.now() - tRouteStart}ms`);
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ export default (router, tpl) => {
|
|||||||
avatar: row.avatar_file ? `/a/${row.avatar_file}` : (row.avatar ? `/t/${row.avatar}.webp` : '/a/default.png'),
|
avatar: row.avatar_file ? `/a/${row.avatar_file}` : (row.avatar ? `/t/${row.avatar}.webp` : '/a/default.png'),
|
||||||
username_color: row.username_color || null,
|
username_color: row.username_color || null,
|
||||||
stamp: row.stamp,
|
stamp: row.stamp,
|
||||||
timeago: lib.timeAgo(new Date(row.stamp * 1e3).toISOString()),
|
timeago: lib.timeAgo(new Date(row.stamp * 1e3).toISOString(), req.lang),
|
||||||
tags: row.tag_list || '',
|
tags: row.tag_list || '',
|
||||||
is_oc: row.is_oc || false,
|
is_oc: row.is_oc || false,
|
||||||
is_faved: row.is_faved || false,
|
is_faved: row.is_faved || false,
|
||||||
|
|||||||
@@ -923,49 +923,8 @@
|
|||||||
window.f0ckAllowedImages = {{ allowed_comment_images_json }};
|
window.f0ckAllowedImages = {{ allowed_comment_images_json }};
|
||||||
window.scrollerPublic = {{ private_society ? 'false' : 'true' }};
|
window.scrollerPublic = {{ private_society ? 'false' : 'true' }};
|
||||||
window.scrollerMimeCats = {{ JSON.stringify(scroller_mime_cats) }};
|
window.scrollerMimeCats = {{ JSON.stringify(scroller_mime_cats) }};
|
||||||
@if(typeof session !== 'undefined' && session)
|
|
||||||
window.scrollerUsername = "{{ session.user || '' }}";
|
|
||||||
window.scrollerDisplayName = "{{ session.display_name || session.user || '' }}";
|
|
||||||
window.scrollerUserAvatar = "{{ session.avatar_file ? '/a/' + session.avatar_file : (session.avatar ? '/t/' + session.avatar + '.webp' : '/a/default.png') }}";
|
|
||||||
window.f0ckI18n = {
|
window.f0ckI18n = {
|
||||||
// notifications
|
lang: "{{ lang }}",
|
||||||
notif_upload_approved: "{{ t('notifications.upload_approved_short') }}",
|
|
||||||
notif_upload_pending: "{{ t('notifications.upload_pending_short') }}",
|
|
||||||
notif_new_report: "{{ t('notifications.new_report_short') }}",
|
|
||||||
notif_upload_denied: "{{ t('notifications.upload_denied_short') }}",
|
|
||||||
notif_upload_deleted: "{{ t('notifications.upload_deleted_short') }}",
|
|
||||||
notif_upload_success: "{{ t('notifications.upload_success') }}",
|
|
||||||
notif_upload_error: "{{ t('notifications.upload_error') }}",
|
|
||||||
notif_replied: "{{ t('notifications.replied_short') }}",
|
|
||||||
notif_subscribed: "{{ t('notifications.subscribed_short') }}",
|
|
||||||
notif_mentioned: "{{ t('notifications.mentioned_short') }}",
|
|
||||||
notif_commented: "{{ t('notifications.commented') }}",
|
|
||||||
notif_system: "{{ t('notifications.system') }}",
|
|
||||||
notif_admin: "{{ t('notifications.admin') }}",
|
|
||||||
notif_moderation: "{{ t('notifications.moderation') }}",
|
|
||||||
notif_tab_user: "{{ t('nav.notif_tab_user') }}",
|
|
||||||
notif_tab_system: "{{ t('nav.notif_tab_system') }}",
|
|
||||||
no_notifications: "{{ t('nav.no_notifications') }}",
|
|
||||||
// scroller
|
|
||||||
just_now: "{{ t('scroller.just_now') }}",
|
|
||||||
add: "{{ t('scroller.add') }}",
|
|
||||||
update_preset: "{{ t('scroller.update_preset') }}",
|
|
||||||
update_preset_sub: "{{ t('scroller.update_preset_sub') }}",
|
|
||||||
no_presets: "{{ t('scroller.no_presets') }}",
|
|
||||||
copy_clipboard: "{{ t('scroller.copy_clipboard') }}",
|
|
||||||
copied: "{{ t('scroller.copied') }}",
|
|
||||||
recent: "{{ t('scroller.recent') }}",
|
|
||||||
nothing_found: "{{ t('scroller.nothing_found') }}",
|
|
||||||
adjust_filters: "{{ t('scroller.adjust_filters') }}",
|
|
||||||
failed_load_comments: "{{ t('scroller.failed_load_comments') }}",
|
|
||||||
no_custom_emojis: "{{ t('scroller.no_custom_emojis') }}",
|
|
||||||
login_required: "{{ t('scroller.login_required') }}",
|
|
||||||
rehost_failed: "{{ t('scroller.rehost_failed') }}",
|
|
||||||
chan_load_failed: "{{ t('scroller.chan_load_failed') }}",
|
|
||||||
fetch_failed: "{{ t('scroller.fetch_failed') }}",
|
|
||||||
invalid_chan_url: "{{ t('scroller.invalid_chan_url') }}",
|
|
||||||
chan_catalog_failed: "{{ t('scroller.chan_catalog_failed') }}",
|
|
||||||
anonymous: "{{ t('scroller.anonymous') }}",
|
|
||||||
// timeago
|
// timeago
|
||||||
ta_just_now: "{{ t('timeago.just_now') }}",
|
ta_just_now: "{{ t('timeago.just_now') }}",
|
||||||
ta_second: "{{ t('timeago.second') }}",
|
ta_second: "{{ t('timeago.second') }}",
|
||||||
@@ -997,8 +956,56 @@
|
|||||||
add_to_site_first: "{{ t('scroller.add_to_site_first') }}",
|
add_to_site_first: "{{ t('scroller.add_to_site_first') }}",
|
||||||
// reply
|
// reply
|
||||||
replying_to: "{{ t('scroller.replying_to') }}",
|
replying_to: "{{ t('scroller.replying_to') }}",
|
||||||
reply: "{{ t('scroller.reply') }}"
|
reply: "{{ t('scroller.reply') }}",
|
||||||
|
// scroller labels
|
||||||
|
just_now: "{{ t('scroller.just_now') }}",
|
||||||
|
failed_load_comments: "{{ t('scroller.failed_load_comments') }}",
|
||||||
|
no_comments: "{{ t('scroller.no_comments') }}",
|
||||||
|
write_comment: "{{ t('scroller.write_comment') }}",
|
||||||
|
login_required: "{{ t('scroller.login_required') }}",
|
||||||
|
login_to_comment: "{{ t('scroller.login_to_comment') }}"
|
||||||
};
|
};
|
||||||
|
@if(typeof session !== 'undefined' && session)
|
||||||
|
window.scrollerUsername = "{{ session.user || '' }}";
|
||||||
|
window.scrollerDisplayName = "{{ session.display_name || session.user || '' }}";
|
||||||
|
window.scrollerUserAvatar = "{{ session.avatar_file ? '/a/' + session.avatar_file : (session.avatar ? '/t/' + session.avatar + '.webp' : '/a/default.png') }}";
|
||||||
|
Object.assign(window.f0ckI18n, {
|
||||||
|
// notifications
|
||||||
|
notif_upload_approved: "{{ t('notifications.upload_approved_short') }}",
|
||||||
|
notif_upload_pending: "{{ t('notifications.upload_pending_short') }}",
|
||||||
|
notif_new_report: "{{ t('notifications.new_report_short') }}",
|
||||||
|
notif_upload_denied: "{{ t('notifications.upload_denied_short') }}",
|
||||||
|
notif_upload_deleted: "{{ t('notifications.upload_deleted_short') }}",
|
||||||
|
notif_upload_success: "{{ t('notifications.upload_success') }}",
|
||||||
|
notif_upload_error: "{{ t('notifications.upload_error') }}",
|
||||||
|
notif_replied: "{{ t('notifications.replied_short') }}",
|
||||||
|
notif_subscribed: "{{ t('notifications.subscribed_short') }}",
|
||||||
|
notif_mentioned: "{{ t('notifications.mentioned_short') }}",
|
||||||
|
notif_commented: "{{ t('notifications.commented') }}",
|
||||||
|
notif_system: "{{ t('notifications.system') }}",
|
||||||
|
notif_admin: "{{ t('notifications.admin') }}",
|
||||||
|
notif_moderation: "{{ t('notifications.moderation') }}",
|
||||||
|
notif_tab_user: "{{ t('nav.notif_tab_user') }}",
|
||||||
|
notif_tab_system: "{{ t('nav.notif_tab_system') }}",
|
||||||
|
no_notifications: "{{ t('nav.no_notifications') }}",
|
||||||
|
// scroller
|
||||||
|
add: "{{ t('scroller.add') }}",
|
||||||
|
update_preset: "{{ t('scroller.update_preset') }}",
|
||||||
|
update_preset_sub: "{{ t('scroller.update_preset_sub') }}",
|
||||||
|
no_presets: "{{ t('scroller.no_presets') }}",
|
||||||
|
copy_clipboard: "{{ t('scroller.copy_clipboard') }}",
|
||||||
|
copied: "{{ t('scroller.copied') }}",
|
||||||
|
recent: "{{ t('scroller.recent') }}",
|
||||||
|
nothing_found: "{{ t('scroller.nothing_found') }}",
|
||||||
|
adjust_filters: "{{ t('scroller.adjust_filters') }}",
|
||||||
|
no_custom_emojis: "{{ t('scroller.no_custom_emojis') }}",
|
||||||
|
rehost_failed: "{{ t('scroller.rehost_failed') }}",
|
||||||
|
chan_load_failed: "{{ t('scroller.chan_load_failed') }}",
|
||||||
|
fetch_failed: "{{ t('scroller.fetch_failed') }}",
|
||||||
|
invalid_chan_url: "{{ t('scroller.invalid_chan_url') }}",
|
||||||
|
chan_catalog_failed: "{{ t('scroller.chan_catalog_failed') }}",
|
||||||
|
anonymous: "{{ t('scroller.anonymous') }}"
|
||||||
|
});
|
||||||
@endif
|
@endif
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user