您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Ergänzungen für die Romeo-Website
当前为
// ==UserScript== // @name RomeoEnhancer // @version 1.12.2 // @author braveguy (Romeo: braveguy / Gruppe RomeoEnhancer) // @description Ergänzungen für die Romeo-Website // @require https://code.jquery.com/jquery-3.7.0.min.js // @match https://*.romeo.com/* // @match https://83.98.143.20/* // @match https://www.hunqz.com/* // @run-at document-body // @copyright braveguy 12.10.2016 / 02.04.2024 // @namespace https://gf.qytechs.cn/users/139428 // ==/UserScript== /** * Copyright(c) braveguy (Romeo: braveguy / Gruppe RomeoEnhancer) * * Änderungen oder die Wiederverwendung von Code von RomeoEnhancer * erfordern meine ausdrückliche Zustimmung. Es ist nicht gestattet, * geänderte Versionen von RomeoEnhancer zu veröffentlichen. * * Das Skript wurde mit Tampermonkey in aktuellen Versionen von Safari, Chrome * und Firefox getestet. Dennoch geschieht die Benutzung auf eigenes Risiko. * * ** Datenschutz ** * RomeoEnhancer enthält keinerlei Code, um Nutzer zu identifizieren * oder Daten auszuspähen. Es besteht keinerlei geschäftliches Interesse. * * Die aktuelle Version von RomeoEnhancer ist verfügbar unter: * https://gf.qytechs.cn/scripts/31282-romeoenhancer * * * ****** English version ***** * * Copyright(c) by braveguy (Romeo: braveguy / group RomeoEnhancer) * * Modifications and/or reuse of RomeoEnhancer code require my explicit consent. * You are NOT allowed to publish any changed version of RomeoEnhancer! * * All code has been tested with Tampermonkey in a recent Safari, Chrome, * and Firefox browser. However, the use of this script is at your own risk. * * ** Privacy ** * RomeoEnhancer does NOT and never will include any code to identify you * or spy on your data. There is no commercial interest. * * The latest version of RomeoEnhancer is available on: * https://gf.qytechs.cn/scripts/31282-romeoenhancer */ // ***** Use RE_addStyle instead of GM_addStyle to work with both Gear Browser and Userscripts ***** if (typeof RE_addStyle == 'undefined') { this.RE_addStyle = (aCss) => { 'use strict'; let head = document.querySelector('head'); if (head) { let style = document.createElement('style'); style.setAttribute('type', 'text/css'); style.textContent = aCss; head.appendChild(style); return style; } return null; }; } // ***** CSS ***** //background colors let color1 = '', color2 = '', color3 = '', color4 = '', color5 = '', color6 = '', color7 = '', color8 = '', color9 = ''; //localStorage.setItem('REcolorScheme', 'retroBlue') switch (localStorage.getItem('REcolorScheme')) { case 'sexyDark': // Romeo default - Sexy Dark break; case 'lighterGrey': // Lighter Grey color1 = '#1f1f1f', color2 = '#1f1f1f', color3 = '#000', color4 = '#101010', color5 = '#1a1a1a', color6 = '#f0f0f0', color7 = '#cc2d2d', color8 = '#2a2a2a', color9 = '#2a2a2a'; break; case 'retroBlue': // Retro Blue color1 = '#102c54', color2 = '#102c54', color3 = '#000', color4 = '#101010', color5 = '#122646', color6 = '#f0f0f0', color7 = '#f0f0f0', color8 = 'rgba(255,255,255,.08)', color9 = '#30415d'; break; case 'fineGrey': // RE default - Fine Grey default: color1 = '#1a1a1a', color2 = '#171717', color3 = '#000', color4 = '#101010', color5 = '#232323', color6 = '#f0f0f0', color7 = '#cc2d2d', color8 = '#2a2a2a', color9 = '#2a2a2a'; break; } RE_addStyle ( //tweak dark design `html.js body, .js-main-stage, .stream__content, .layer__column--background, .layer__column--detail, #group-preview .layer__container, .profile .below-fold, .profile-section {background-color:${color1} !important}` + `div.js-wrapper section[class^="Section"], div.js-wrapper div[class^="slider_wrapper-"]:before, div.js-wrapper div[class^="slider_wrapper-"]:after {background-color:${color1} !important}` + `.Xcontent-nav, .Xcontent-nav__actions, .ui-navbar--app, .filter-container {background-color:${color2} !important}` + `.listitem--selected > div {background-color:${color9} !important}` + `li[class^="stat-bar__item--"] {background-color:${color2}}` + `.listresult {background-color:${color2}}` + `.listresult:hover, :is(.js-chat, .js-contacts) .reactView > div:hover {background-color:${color8} !important}` + `.js-profile-footprints section {background-color:${color8}}` + `.listresult .list-stat-bar__item, .icon-circular.icon-u {background-color:transparent}` + `.WGgGs .reactView > button {background-color:${color9} !important}` + `:is(.js-post-edit, .js-post-list, #post, #group-post) textarea {background-color:${color4} !important}` + `.js-post-edit button[class*="ActionButton"] {background-color:${color1}}` + `.js-post-edit div[class*="Wrapper-"] {background-color:${color5} !important}` + `.js-post-list div[class^="Container"], :is(#group-post, #post) :is(.js-post, .js-post div[class^="Container"], div.js-comment) {background-color:${color5} !important}` + `section.js-main-stage div[class^="Grid-"] div[class*="Wrapper-"], section.js-main-stage div[class^="Grid-"] + div[class^="Wrapper-"] {background-color:${color5} !important}` + `.messages-list__content, .messages-send {background-color:${color2}!important}` + `:is(.js-profile-contact, #messenger .js-detail) > div > div, :is(.js-profile-contact, .js-detail) > div > div > div > div:last-child {background-color:${color2}!important}` + `.messages-send__form-input {background-color:${color3}!important}` + `:is(.WGgGs, .js-main .js-navigation li) svg[class^="Icon__Svg-sc-"] {color:${color7}}` + `:is(.search-results--list-style > div, .grouped-tiles-list .refreshable) > div:nth-child(odd) .reactView > div {background-color:${color5}}` + `:is(.search-results--list-style > div, .grouped-tiles-list .refreshable) > div:nth-child(even) .reactView > div {background-color:${color1}}` + //bigger text in messages, groups, profiles; wrap long links ':is(#messages-list div.reactView, :is(.js-post-list, .js-post, .js-profile-text, .js-description) div[class^="TruncateBlock__Content-"]) > p[class^="BaseText-sc-"],' + '.profile section.profile__stats details > div > p[class^="BaseText-sc-"],' + ':is(.stream__content, .js-chat, .js-correspondence, .js-contacts, .js-username, .WGgGs, .js-actions, #manage, .js-profile-reviews) [class^="BodyText-sc-"],' + '[class^="ResponsiveBodyText-"] {font-size:.9375rem !important; letter-spacing:normal !important; line-height:1.375 !important; word-break:break-word !important}' + //avatar icon ':is(.layer-left-navigation, header li) div[class^="OnlineStatus"] svg[viewBox="0 0 10 12"] {width:.75rem; height:.75rem}' + //icons, links 'a.re-icon {position:relative; top:.1em; font-size:.9em}' + ':is(div.BIG, div.SMALL, div.LIST, .js-contacts) a.re-icon {position:relative; top:0}' + ':is(div.LIST, .js-contacts, .js-username) a.re-icon {font-size:.825em}' + 'a.re-idle, a.re-idle-no-hover, a.re-idle-no-hover:hover {color:inherit !important}' + ':is(a.re-icon:hover, a.re-idle, Xa.re-icon-visitor, Xa.re-icon visited):hover {color:rgba(102,215,255,.8) !important}' + 'a.re-link, a.re-link-no-hover {color:#00bdff}' + '[class*="hunqz"] a.re-link {color:#fc193c}' + 'a.re-link-idle {color:unset !important}' + ':is(a.re-link, a.re-link-idle, .js-report-icon svg):hover {color:#66d7ff !important}' + '[class*="hunqz"] :is(a.re-link, a.re-link-idle, a.re-icon, .js-report-icon svg):hover {color:#fd5871 !important}' + 'a[class*="Tabbed-nav-link-"] {font-size:1.05rem}' + //discover page ':is(a.re-eyecandy-active, a.re-eyecandy-active:hover) span {display:none; margin: 0 .25rem 0 .5rem; font-size:.875rem; color:rgba(255,255,255,1) !important; text-transform:none; font-family:Inter; font-weight:normal}' + 'a.re-eyecandy-active.is-selected span:first-child, a.re-eyecandy-active:not(.is-selected) span:nth-child(2) {display:inline}' + 'a.re-eyecandy-active svg {margin-bottom:.125rem}' + 'a.re-eyecandy-active svg path {fill:currentcolor}' + //filter icon, bookmark name //'.re-filter-bookmark-name {position:absolute; right:0}' + '.is-filter-collapsed .re-filter-bookmark-name {display:none!important}' + '.is-filter-opened .re-filter-options-text, .is-filter-opened div.js-filter-button svg + span + span:not(.re-filter-bookmark-name) {display:none!important}' + //expand truncated location names on hover '.typo-small.txt-truncate:hover {white-space:normal; word-break:break-all}' + //tiles ':is(div.BIG, div.SMALL, div.LIST) > div:first-child [class^="SpecialText"] {filter:drop-shadow(rgba(0,0,0,.5) 0 1px 1px) drop-shadow(rgba(0,0,0,.5) 1px 1px 0)}' + 'div.tile p[class^="SpecialText"] {word-break:break-word}' + 'div.tile p[class^="SpecialText"]:hover {white-space:normal}' + 'div.tile--plus span[class^="SpecialText"] {background-color:rgb(38,38,38)}' + //list view 'div:has(> .LIST) + div {margin-top:.5rem}' + //messenger '.message:not(.message--sent) .message__content {background:hsla(0,0%,100%,.125)}' + '.message:not(.message--sent) .message__content:before {border-color: transparent transparent hsla(0,0%,100%,.125); left:-9px}' + '.message:not(.message--sent) .message__attachments {background-color:transparent}' + '.message__status {color:rgba(255,255,255,.5)!important}' + ':is(.js-chat, #manage) div[class^="OnlineStatus"] > div > svg {height:13px; width:13px}' + ':is(.js-chat, #manage) div[class^="OnlineStatus"] > div > svg[viewBox="0 0 10 12"] {height:15px; width:15px}' + 'p[class*="OnlineStatus__TimeString"] {line-height:1}' + '.js-chat .js-scrollable {max-height:1270px !important}' + '.js-chat .typo-headline-small {font-size:inherit}' + '.fQIYNa {font-weight:550}' + '.online-favourites__item {margin:0 .475rem !important}' + '.online-favourites__itemName {width:4rem; margin:0 -.125rem}' + 'section.emoji-mart button.emoji-mart-anchor:hover {color:rgba(255,255,255,.5)}' + '.js-chat p[class^="BodyText-sc-"] {opacity:.87; column-gap:.25rem}' + '.js-chat a[href^="/messenger"] > div > span {opacity:.87}' + '.js-chat a > span > span svg[viewBox="0 0 9 7"] {height:9px; width:11px; opacity:.66}' + '.js-chat a > span > span svg[viewBox="0 0 12 12"] {height:15px; width:15px}' + '#messenger .js-header-region > div > h1 {padding-top:1.2rem}' + '#messenger .js-header-region > div > h1 a:has(span) {padding-bottom:.85rem}' + '#messenger .js-header-region .reactView > div > div > :is(div, a) {position:absolute; top:-1.2rem}' + '#messenger .re-login-location {position:absolute; top:0; width:100%}' + '#messenger .re-login-location > div {position:absolute; font-size:.75rem; font-weight:500; opacity:.8; background-color:transparent}' + '#messenger .re-msg-location {top:0; width:100%; padding:.25rem 0 0 3rem}' + '#messenger .re-msg-location a {padding-top:3px}' + '#messenger .re-msg-login {top:2.7rem; left:4rem; line-height:.85rem; min-width:10rem; padding-left:3rem; margin-right:5rem}' + '#messenger .re-msg-offline {top:2.7rem; left:3rem; line-height:.85rem}' + '.messages-send__form textarea.input--chat {padding-right:.5rem}' + ':is(.js-correspondence .js-header-region, #manage) div[class*="ContextMenu__"] ul {width:15.25rem; max-width:15.25rem !important}' + '.js-contacts div > div > button > svg {height:21px; width:21px}' + 'ul[class^="TagCloud__UnstyledList"] button {font-size:.875rem; line-height:1.25}' + ':is(.js-detail, .js-profile-contact) p[class^="ResponsiveBodyText-"] + :is(span, p) {font-size:.875rem !important; padding-bottom:.25rem}' + '.js-chat .listitem--selected {border-right:5px solid #fff}' + '.js-chat .refreshable .reactView {min-height:6rem}' + '.js-contacts .listitem--selected > div {border-left:5px solid #fff}' + //stream 'div.stream__content div.tile div[class^="OnlineStatus"] {position:absolute; left:-8px; top:-8px}' + 'div.stream__content div.tile div[class^="OnlineStatus"] > div {display:flex; align-items:center; justify-content:center; background-color:#1f1f1f; border-radius:50%; height:19px; width:19px; margin-top:0!important}' + 'div.stream__content div.tile div[class^="OnlineStatus"] svg {height:12px; width:12px}' + 'div.stream__content div.tile div[class^="OnlineStatus"] svg[viewBox="0 0 10 12"] {height:13px; width:13px}' + '.listitem .emoji:hover {font-size:1.5rem; line-height:1.33rem; margin-left:-.4rem; position:relative; right:-.2rem; padding-bottom:.33rem}' + '.stream__content .listitem {min-height:4.8rem}' + //profile stats, separators, icons '.profile__info p {word-break:break-word}' + '.profile div[aria-label] > div[role="figure"] {border-color:rgba(255,255,255,0.33)}' + '.profile .re-profile-stats {font-size:.825rem; color:rgba(255,255,255,0.6)}' + '.re-img-count {position:absolute; bottom:.5rem; left:.5rem; display:flex; align-items:center; justify-items:center}' + '.re-img-count div {color:rgba(255,255,255,.87); background-color:rgb(18,18,18); border-radius:.125rem; padding:0 .25rem; height:1.125rem; line-height:1rem}' + '.profile__image-strip .re-img-count {margin-left:.5rem}' + '.js-profile-footprints section:last-child {padding-top:7.5rem}' + '.js-profile-footprints section + section:last-child {padding-top:0}' + '.js-profile-footprints.re-zoom section:last-child {grid-template-columns:repeat(3,33%)}' + '.js-profile-footprints.re-zoom section:last-child button {background-size:72px 72px; height:77px; width:72px; border-bottom-width:5px}' + '.js-profile-footprints.re-zoom section:last-child label p {max-width:14ch}' + //slideshow 'div.swiper-wrapper {margin-top:2rem}' + 'div.swiper-zoom-container > img {min-height:75%}' + '#metadata-bar > div > div > a {margin-left:0}' + '#metadata-bar > div > div a + p > a {margin-left:.33em; display:inline}' + '#metadata-bar > div:first-child > div + p {margin:0 0 .5rem 0; font-size:.8125rem !important; color:rgba(255,255,255,.66); text-transform:uppercase}' + '#metadata-bar > div:first-child > div:first-child + p[class^="SpecialText"] {text-transform:none}' + '#metadata-bar > div > div > p[class^="ResponsiveBodyText"] {font-size:.875rem !important}' + '#metadata-bar > div > div:nth-last-child(-n+2) {flex-direction:row}' + '#metadata-bar > div > div:nth-last-child(-n+2) button > svg + p {display:none}' + '#metadata-bar > div > div:nth-last-child(-n+2) > button {margin:0 .25rem .25rem 0; order:2}' + '#metadata-bar > div > div:nth-last-child(-n+2) > p {margin:.25rem 0; order:3}' + '#metadata-bar > div > div:last-child {margin-bottom:.25rem}' + '#metadata-bar > div > div:last-child > p {color:rgb(255,255,255,.66)}' + //slideshow in portrait mode (metadata at bottom) '@media screen and (orientation:portrait) {' + 'div.swiper-wrapper {margin-top:0}' + '#metadata-bar:not(.gtvwGw) {background:linear-gradient(transparent,rgba(0,0,0,.4) 2.5rem,rgba(0,0,0,.8))}' + '#metadata-bar:not(.gtvwGw) {backdrop-filter:blur(0px); -webkit-backdrop-filter:blur(0px)}' + '#metadata-bar:not(.gtvwGw) > div > div {margin:0 0 .25rem 0}' + '#metadata-bar:not(.gtvwGw) > div:first-child > div:first-child {margin-bottom:0}' + '#metadata-bar:not(.gtvwGw) > div:first-child > div + p {margin-bottom:0}' + '#metadata-bar:not(.gtvwGw) > div > div:nth-last-child(-n+2) > button {margin-bottom:0}' + '#metadata-bar:not(.gtvwGw) > div > div:last-child {margin-bottom:0}' + 'aside .media-viewer-footer {height:2rem; padding-bottom:.5rem}' + 'aside .media-viewer-footer p {padding-bottom:.5rem}' + '}' + //group tiles 'div[class*="Tile__BaseTile-"] > p + div {position:absolute; bottom:2rem; left:.475rem}' + 'div[class*="Tile__BaseTile-"] > p + div > p {background-color:#121212 !important}' + 'div[class*="Tile__BaseTile-"] > p {margin:0 0 -.125rem}' + '.profile div[class*="Tile__BaseTile-"] > p {margin:0; font-size:.925rem}' + '.re-common-group p:last-child {color:#6ddc00}' + //groups 'nav.re-groups-def, nav.re-groups-enh {position:relative; padding:0 1rem 1rem; height:calc(100% - 3rem); overflow-y:auto}' + 'nav.re-groups-def {display:none}' + '.js-date .reactView span {font-size:.85em}' + '.js-post-list button[class*="ShowMoreButton"].is-hidden {display:block!important}' + '.js-post-list p[class^="BaseText"] > button {margin-top:.25rem}' + 'div[class^="CommentsArea"] div[class^="TruncateBlock__Content"] {-webkit-line-clamp:unset}' + 'div[class^="CommentsArea"] div[class^="TruncateBlock__Container"] p button {display:none}' + '.js-main .js-sidebar {max-height:inherit !important}' + '.js-main .js-sidebar .WGgGs {padding-bottom:1rem}' + '.js-blurred-image > div {z-index:0}' + //groups list 'span.re-posts-view {font-family: "Gibson Bold"; font-weight:500; text-transform:uppercase; background-color:transparent; color:#fff; height:auto; cursor:pointer; padding-left:2rem;}' + 'span.re-list-head, span.re-list-view, span.re-list-load {font-family:Inter,Helvetica,Arial,"Open Sans",sans-serif; text-transform:uppercase; user-select:none; color:rgb(255,255,255,.5); height:auto}' + 'span.re-list-view, span.re-list-load {font-family: "Gibson Bold"; font-weight:500; color:rgb(250,250,250); cursor:pointer;}' + 'span.re-list-load:before {display:inline-block; transform:scaleX(-1)}' + '.re-groups-listitem {font-family:Inter,Helvetica,Arial,"Open Sans",sans-serif; display:flex; align-items:center; border:0; border-radius:.25em; padding:.5em; width:100%}' + `.re-groups-listitem:hover {background-color:${color8}}` + '.re-groups-tile {display:flex; flex-shrink:0; margin-right:1em; background-size:cover; border-radius:50%; height:3em; width:3em}' + '.re-groups-entry {flex-grow:1; flex-shrink:1; min-width:0; display:flex; align-items:center}' + '.re-groups-text {font-size:1em; font-weight:500; line-height:1.375em; word-break:break-word; margin-right:.25em; display:block; overflow:hidden}' + '.re-groups-name {font-size:.9375rem; color:rgb(0,163,228); font-weight:500; display:inline-block; overflow:hidden; text-overflow:ellipsis; word-wrap:normal}' + '.re-groups-time {font-size:.825em; color:rgba(250,250,250,.625)}' + '.re-groups-admin {display:flex; align-items:center; color:rgb(0,0,0,.8); background-color:rgb(0,189,255); padding:0 .25rem; border-radius:.25rem; font-size:0.625rem}' + '.re-groups-new {display:flex; align-items:center; color:rgb(250,250,250,.8); font-size:0.8em}' + '.re-groups-new svg {display:inline-block; height:1em; width:1.125em; vertical-align:middle}' + '.re-groups-new svg path {fill:currentcolor}' + `.re-groups-selected {background-color:${color9}}` + '.re-groups-selected .re-groups-name {color:rgba(255,255,255,.925)}' + '.re-groups-selected .re-groups-new {color:rgba(250,250,250,.425)}' + '.re-groups-selected .re-groups-admin {background-color:rgba(255,255,255,.87)}' + '.re-groups-visited :is(.re-groups-name, .re-groups-new) {color:rgba(250,250,250,.425)}' + '.re-groups-visited .re-groups-time {color:rgba(250,250,250,.375)}' + '.re-groups-visited .re-groups-admin {background-color:rgba(250,250,250,.425)}' + //travel '.re-member-travel, .re-radar-travel, .re-edit-travel {color:#00bdff; text-transform:initial; vertical-align: middle; line-height:inherit !important; cursor:pointer}' + '.re-member-travel:hover, .re-radar-travel:hover, .re-edit-travel:hover {color:#66d7ff}' + '.re-member-travel.re-selected, .re-radar-travel.re-selected {color:#fff}' + //visitor icons 'a.re-icon-visitor, a.re-icon-visited {font-size:1.1em; color:#fff}' + // 'a.re-icon-visitor:before, a.re-icon-visited:before {position:relative; top:1px}' + 'a.re-icon-visited {transform:scaleX(-1)}' + //picture rating '.re-rating-date {position:absolute; top:2.5rem; font-size:.85em; cursor:default}' + //relogin '.re-relogin-frame {background-color:transparent !important}' + '.re-relogin-frame:before {border:none !important}' + //more big tiles per page '@media screen and (min-width:55rem) {' + '.search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:25% !important; width:25% !important}' + ':is(.is-filter-opened, .is-stream-opened) .search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:33.33333% !important; width:33.33333% !important}' + '.is-stream-opened.is-filter-opened div.search-results--big-tiles div.search-results__item:not(.search-results__banner) {padding-bottom:50% !important; width:50% !important} }' + '@media screen and (min-width:75rem) {' + '.search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:20% !important; width:20% !important}' + ':is(.is-filter-opened, .is-stream-opened) .search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:25% !important; width:25% !important}' + '.is-stream-opened.is-filter-opened div.search-results--big-tiles div.search-results__item:not(.search-results__banner) {padding-bottom:33.33333% !important; width:33.33333% !important} }' + '@media screen and (min-width:95rem) {' + '.search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:16.66666% !important; width:16.66666% !important}' + ':is(.is-filter-opened, .is-stream-opened) .search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:20% !important; width:20% !important}' + '.is-stream-opened.is-filter-opened div.search-results--big-tiles div.search-results__item:not(.search-results__banner) {padding-bottom:25% !important; width:25% !important} }' + '@media screen and (min-width:120rem) {' + '.search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:12.5% !important; width:12.5% !important}' + ':is(.is-filter-opened, .is-stream-opened) .search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:16.66666% !important; width:16.66666% !important}' + '.is-stream-opened.is-filter-opened div.search-results--big-tiles div.search-results__item:not(.search-results__banner) {padding-bottom:20% !important; width:20% !important} }' + '@media screen and (min-width:140rem) {' + '.search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:12.5% !important; width:12.5% !important}' + ':is(.is-filter-opened, .is-stream-opened) .search-results--big-tiles .search-results__item:not(.search-results__banner) {padding-bottom:12.5% !important; width:12.5% !important}' + '.is-stream-opened.is-filter-opened div.search-results--big-tiles div.search-results__item:not(.search-results__banner) {padding-bottom:16.66666% !important; width:16.66666% !important} }' + //*** DESKTOP *** '@media screen and (min-width:768px) {' + //general '.re-mobi {display:none!important}' + '.re-touch {visibility:hidden!important}' + //slideshow in portrait window '.ReactModal__Overlay.ReactModal__Overlay--after-open > .ReactModal__Content.ReactModal__Content--after-open > main {background:none}' + '.container-button-next, .container-button-prev {display:flex !important}' + '.swiper-zoom-container > img {height:initial}' + //fix for chat navigation on smaller screens '#messenger ul[class^="Tabbed-nav-"] {width:100vw}' + '}' + //*** DESKTOP >= 1024px *** '@media screen and (min-width:1024px) {' + //stream '.stream {width:18.5rem!important}'+ '}' + //*** TABLET *** '@media screen and (max-width:1024px) {' + //top right navigation 'nav.js-top-right-navigation{display:none}' + '}' + //*** MOBILE *** '@media screen and (max-width:767px) {' + //general '.re-desk {display:none!important}' + '.re-touch {visibility:hidden!important}' + //tweak dark design `.ui-navbar--app, .ui-navbar.content-nav ul {background-color:#000 !important}` + 'div.content-nav--animated {height:3rem}' + //main menu 'a[class*="Tabbed-nav-link-"] {font-size:.875rem}' + //stream 'div.stream__content {top:3.75rem}' + //messages '#messenger .js-header-region > div > h1 {padding-top:1.7rem}' + '#messenger .re-msg-location {padding-top:.75rem}' + '#messenger .re-msg-login {top:3.2rem}' + '#messenger .re-msg-offline {top:3.2rem}' + '.messages-send__form textarea.input--chat {font-size:.9375rem; letter-spacing:normal}' + //slideshow 'div.swiper-wrapper {height:96%; margin-top:0}' + //group tiles 'div[class*="Tile__BaseTile-"] > p {margin:0; font-size:.925rem}' + //picture rating '.re-rating-date {top:3rem}' + //hide groups list when group selected, wrap long group names // 'div[class*="withNav-"] > div[class*="ReactContainer-"] {overflow-x:hidden !important}' + 'div[class*="withNav-"] > div[class*="ReactContainer-"]:not(:has(.re-groups-def)) {flex:0; width:0}' + 'div[class*="withNav-"] > div[class*="ReactContainer-"]:not(:has(.re-groups-def)) > :is(div, nav) {display:none}' + 'div[class*="withNav-"] > div[class*="ReactContainer-"]:has(.re-groups-def) + div.js-main {display:none}' + 'div[class^="NameAndOfficialBadgeWrapper-"] {white-space:unset}' + //back arrow in group post '#group-post .js-post button.js-back {margin:1rem 1rem 0 -.5rem}' + //fix for flickering bottom and top right navigation 'header nav > ul > li:not(:has(path[d^="M20.3943"], path[d^="m20.507"], path[d^="M23.102"], path[d^="M13.493"], path[d^="M6.99 10"], div[style^="background-image"], path[d^="M23 14."], path[d^="M21.548"], path[d^="M21.917"])) {display:none}' + 'nav.js-top-right-navigation {display:none}' + //fix for navbar '.ui-navbar {height:3.5rem}' + 'div.contacts__filters {top:3.5rem}' + 'div.js-nav + div {margin-top:3.5rem}' + //fix to hide floating filter button in eyecandy 'main:has(nav a[href^="/eyecandy/"]) .js-floating-filter-button {display:none}' + '}' + //*** TOUCH SCREEN *** '@media screen and (hover:none) {' + //general '.re-touch {visibility:visible!important}' + //icons, links 'a.re-icon {padding:.25em 0 .25rem .5em; font-size:1em}' + 'div.stream__content a.re-icon {padding:.25em .5em .25em 0}' + 'a.re-eyecandy-active {padding:.25em .5em}' + '}' ); // ***** Clean up old settings ***** localStorage.removeItem('contactsSelection'); localStorage.removeItem('REgroupPostsView'); localStorage.removeItem('reRatingMax'); // ***** Test for mobile or touch device ***** // usage: if (mobile.matches) ...; if (touch.matches) ... let mobile = window.matchMedia("(max-width:767px)"); let touch = window.matchMedia("(hover:none)"); // ************************************************************** // ***** The following function is taken from: // ***** https://gist.github.com/BrockA // ***** https://gist.github.com/raw/2625891/waitForKeyElements.js /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts, that detects and handles AJAXed content. Usage example: waitForKeyElements ( "div.comments" , commentCallbackFunction ); //--- Page-specific function to do what we want when the node is found. function commentCallbackFunction (jNode) { jNode.text ("This comment changed by waitForKeyElements()."); } IMPORTANT: This function requires your script to have loaded jQuery. */ function waitForKeyElements ( selectorTxt, /* Required: The jQuery selector string that specifies the desired element(s). */ actionFunction, /* Required: The code to run when elements are found. It is passed a jNode to the matched element. */ bWaitOnce, /* Optional: If false, will continue to scan for new elements even after the first match is found. */ iframeSelector /* Optional: If set, identifies the iframe to search. */ ) { var targetNodes, btargetsFound; if (typeof iframeSelector == "undefined") targetNodes = $(selectorTxt); else targetNodes = $(iframeSelector).contents () .find (selectorTxt); if (targetNodes && targetNodes.length > 0) { btargetsFound = true; /*--- Found target node(s). Go through each and act if they are new. */ targetNodes.each ( function () { var jThis = $(this); var alreadyFound = jThis.data ('alreadyFound') || false; if (!alreadyFound) { //--- Call the payload function. var cancelFound = actionFunction (jThis); if (cancelFound) btargetsFound = false; else jThis.data ('alreadyFound', true); } } ); } else { btargetsFound = false; } //--- Get the timer-control variable for this selector. var controlObj = waitForKeyElements.controlObj || {}; var controlKey = selectorTxt.replace (/[^\w]/g, "_"); var timeControl = controlObj [controlKey]; var timerInterval = (document.visibilityState === "visible" ? 750 : 1500); //--- Now set or clear the timer as appropriate. if (btargetsFound && bWaitOnce && timeControl) { //--- The only condition where we need to clear the timer. clearInterval (timeControl); delete controlObj [controlKey]; } else { //--- Set a timer, if needed. if ( ! timeControl ) { timeControl = setInterval ( function () { waitForKeyElements (selectorTxt, actionFunction, bWaitOnce, iframeSelector ); }, timerInterval ); controlObj [controlKey] = timeControl; } } waitForKeyElements.controlObj = controlObj; } // ***** end // ************************************************************** // ***** Set AJAX headers ***** let key0 = window.atob('WC1TZXNzaW9uLUlk'); let key1 = window.atob('WC1BcGktS2V5'); let val1 = window.atob('OEpOdlBiVjNJOUtMaU5xUFNxc2NOVFllZzd1aXd2TUk='); function ajaxHead(){ return {[key0]: JSON.parse(localStorage.getItem('PR_SETTINGS:SESSION_ID')), [key1]: val1}; } // ***** Replace URLs with links ***** // ***** Adopted from https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links/37687#37687 ***** function linkify(text) { //Email addresses let pattern1 = /(^|\s|<br>)(([-\w\.\+])+@[-\w]+?(\.[A-Z]{2,6})+)/gim; text = text.replace(pattern1, '$1<a href="mailto:$2" class="plain-text-link">$2</a>'); //URLs starting with http:// or https:// let pattern2 = /(^|\s|<br>)(https?:\/\/[-\w+&@#\/\(\)%?=~|!:,.;]*[-\w+&@#\/\(\)%=~|])/gim; text = text.replace(pattern2, '$1<a target="_blank" href="$2" rel="noreferrer noopener" class="plain-text-link">$2</a>'); //URLs without http:// or https:// let pattern3 = /(^|\s|<br>)([-\w]+\.[a-z][-\w+&#\/\(\)%?=~|!:,.;]*[-\w+&#\/\(\)%=~|])/gm; text = text.replace(pattern3, '$1<a target="_blank" href="http://$2" rel="noreferrer noopener" class="plain-text-link re-link-idle">$2</a>'); //keep internal links in same window let pattern4 = /(target="_blank" )(href="https?:\/\/(www\.)?((planet)?romeo|hunqz)\.com)/gim; text = text.replace(pattern4, '$2'); return text; } // ***** Format date/time ***** function dateTime(timeStamp, dateOnly, noYesterday) { // 1s...59s; 1min...59min; hh:mm; gestern hh:mm; Mo...So, hh:mm; tt.mm.jjjj, hh:mm let timeNow = new Date(); let timeNow1 = new Date (timeNow - 1000*60*60*24); let timeNow7 = new Date (timeNow - 1000*60*60*24*7); let hhmm = {hour: "numeric", minute: "numeric"}; // console.log('dateTime'); if (timeStamp) { if (timeStamp.toDateString() == timeNow.toDateString()) { // today return timeStamp.toLocaleString('de-DE', hhmm); } else if (!noYesterday && timeStamp.toDateString() == timeNow1.toDateString()) { // yesterday return `gestern ${timeStamp.toLocaleString('de-DE', hhmm)}`; } else if (timeStamp > timeNow7 && timeStamp.getDay() != timeNow.getDay()) { // last 6 days of week return timeStamp.toLocaleString('de-DE', {weekday: 'short', hour: "numeric", minute: "numeric"}); } else { return `${timeStamp.toLocaleDateString('de-DE')}${dateOnly ? `` : `, ${timeStamp.toLocaleString('de-DE', hhmm)}`}`; } } } // ***** Format weekday/time ***** function weekTime(timeStamp, dateOnly) { // console.log('weekTime'); return dateTime(timeStamp, dateOnly, true); } // ***** Change URL without reloading the page ***** function changeUrl(url) { history.pushState({}, document.title, url); history.pushState({}, document.title, url); history.back(); } // ***** Change object property in sessionStorage ***** function setSessionStorageItem(storageItem, key, value) { let storageValue = JSON.parse(sessionStorage.getItem(storageItem)); (storageValue) ? storageValue[key] = value : storageValue = JSON.parse(`{"${key}":"${value}"}`); sessionStorage.setItem(storageItem, JSON.stringify(storageValue)); } // ***** Change object property in localStorage ***** function setLocalStorageItem(storageItem, key, value) { let storageValue = JSON.parse(localStorage.getItem(storageItem)); (storageValue) ? storageValue[key] = value : storageValue = JSON.parse(`{"${key}":"${value}"}`); localStorage.setItem(storageItem, JSON.stringify(storageValue)); } // ***** Add title and aria-label ***** jQuery.fn.titleLabel = function(text) { return $(this).attr({'title': text, 'aria-label': text}); }; // ***** Open message thread or contact info by profile name ***** // (not working for blocked, blocking, or deactivated profiles) function openByName(baseUrl, profileLink, profileName) { let profileType = 'profiles'; if (profileLink.match(/^\/hunq\//)) { profileType = 'hunqz/profiles'; /*} else if (profileLink.match(/^\/groups?\//)) { profileType = 'groups';*/ } $.ajax({url: `/api/v4/${profileType}?pick=items.*.(id,name)&lang=de&length=1&filter[fulltext_search_mode]=EXACT&filter[fulltext]=@${profileName}`, headers: ajaxHead() }) .done(function (data) { if (data.items[0] && data.items[0].name == profileName) { changeUrl(baseUrl + data.items[0].id); /* } else { $.ajax({headers: ajaxHead(), url: `/api/v4/${profileType}/${profileName}/full?lang=de&lookup_type=NAME`}) .done(function (data) { if (data.id) { changeUrl(baseUrl + data.id); } }); */ } }); } // ***** Hide visit ***** function hideVisit(profileId) { if (profileId > 0) { $.ajax({url: `/api/v4/visits/${profileId}`, headers: ajaxHead(), method: 'DELETE' }) .done(function () { $('div.profile-topnav__hide').attr('style', 'visibility:hidden'); $('.profile .top-info-header button').attr('style', 'color:rgb(168,168,168)'); }) } } // ***** Search profile id, open profile name directly ***** function searchInput(jNode) { $('#search a.re-add').off('click').remove(); $(jNode).on('input click', function() { let inputValue = $(jNode).val(); $('#search a.re-add').off('click').remove(); if (inputValue.match(/^[1-9]\d{2,}$/)) { $('#search div.js-input').after( `<a style="font-size:1rem" class="re-add re-link-no-hover mr-"><span class="re-desk">Profil-ID ${inputValue} anzeigen</span><span class="re-mobi">ID anzeigen</span></a>` ).next('.re-add').click(function() { openById(inputValue); return false; }); } else if (inputValue.match(/^@?[-\w\/]{3,}$/)) { inputValue = inputValue.replace(/^@/, ''); $('#search div.js-input').after( `<a style="font-size:1rem" class="re-add re-link-no-hover mr-"><span>${inputValue}</span><span class="re-desk"> anzeigen</span></a>` ).next('.re-add').click(function() { changeUrl(((inputValue.match(/^\//)) ? '' : '/profile/') + inputValue); return false; }); } }); } // ***** Open profile by ID ***** function openById(id) { $.ajax({headers: ajaxHead(), url: `/api/v4/profiles/${id}?expand=partner&lang=de`}) .done(function (data) { let type = (data.type) ? data.type : ''; let name = (data.name) ? data.name : ''; let profileType = 'profile'; if (type == 'ESCORT') { profileType = 'hunq'; } else if (type == 'CLUB') { profileType = 'group'; } changeUrl(`/${profileType}/${name}`); }) .fail(function (data) { changeUrl('/profile/-'); }); } // ***** Picture upload month/year ***** //init const imgTable = [ 0x00000000,0x00000000,0x000076f1,0x0000c0c2,0x000113ac,0x000193c7,0x00022adb,0x0002e59b,0x0003c274,0x0004bdda,0x0005cb8f,0x0006f792, //2003 0x00083008,0x0009e166,0x000bc399,0x000dc70d,0x000fcad1,0x001219f5,0x0014e794,0x00180a61,0x001b7a83,0x001eeaaa,0x0022a968,0x0026aaf2, //2004 0x002b6a0f,0x00313036,0x00367804,0x003c4ae9,0x00421a3c,0x0048a2b6,0x004f0ba9,0x00563896,0x005d4ff9,0x00642853,0x006bc702,0x0072dc7c, //2005 0x007a2388,0x0082636e,0x0089c239,0x00921763,0x009ae5e4,0x00a3f472,0x00acfdc3,0x00b72e9e,0x00c1e7a3,0x00cb8a2a,0x00d5c06a,0x00df6215, //2006 0x00e909cb,0x00f428f1,0x00fe1934,0x0108f04e,0x01141330,0x011ffb48,0x012b9597,0x0137a3d7,0x01436c46,0x014eba63,0x015aea4f,0x01665b6d, //2007 0x01721df4,0x017ecdd9,0x018a872f,0x0197cf93,0x01a3fca7,0x01b1bb65,0x01bf7fca,0x01ce1b0e,0x01dd38f7,0x01eb50f3,0x01fa29a3,0x02086e83, //2008 0x0216e0ea,0x0226de08,0x0234eda5,0x02552d86,0x02677f82,0x027aae57,0x028d94f9,0x02a17765,0x02b5e176,0x02c9adb5,0x02dd8aa7,0x02f0dfe7, //2009 0x0304f979,0x031b4142,0x032e6143,0x0342c960,0x0356cd19,0x036cb45e,0x0381a103,0x039883d7,0x03b0829f,0x03c679e3,0x03dd820b,0x03f432a3, //2010 0x040af127,0x0423ddbb,0x0439c102,0x045272f4,0x046b187c,0x048570e5,0x04a07ac1,0x04bcdec4,0x04d9b4fa,0x04f52906,0x05120af3,0x052df05d, //2011 0x054a17b7,0x0568a266,0x0584c8a7,0x05a25176,0x05c0b41b,0x05df82c6,0x05fe3605,0x061e623c,0x063f4240,0x065e2c95,0x067e22b7,0x069dbc58, //2012 0x06c0432b,0x06e65935,0x0707d372,0x072df9eb,0x0751ca91,0x077860fb,0x079c0f3e,0x07c1e771,0x07e86366,0x080da8ce,0x0831ee79,0x08558d00, //2013 0x087b94b3,0x08a21c54,0x08c4f55c,0x08eac6fe,0x09119caa,0x0939b66c,0x0960b60a,0x098a9925,0x09b76f87,0x09e01456,0x0a0906c0,0x0a305fc4, //2014 0x0a80e9b0,0x0adaf553,0x0b2947ce,0x0b7d3b5d,0x0bcf0d62,0x0c24958c,0x0c755b5b,0x0ccd27fa,0x0d23c304,0x0d7376dc,0x0dc5b8fb,0x0e13f084, //2015 0x0e65d6e6,0x0ebdf2c6,0x0f0ce2ec,0x0f607bf5,0x0fb37151,0x100aaf7e,0x105e79ed,0x10b8bbbf,0x1115d90f,0x116ae5ac,0x11be74a4,0x12120bad, //2016 0x1267b822,0x12c42272,0x1315847b,0x136e2e9c,0x13c5fdbd,0x141f2328,0x147b0f3e,0x14ddb823,0x1541cb7a,0x159e4a36,0x1601fff2,0x16657d11, //2017 0x16cb8a49,0x1734ece1,0x1792be94,0x17fa4016,0x185ec78c,0x18c99770,0x193230d2,0x19a225bd,0x1a12bd1e,0x1a79217a,0x1ae1e760,0x1b4790fd, //2018 0x1bb4f607,0x1c23ce64,0x1c84b186,0x1cf2f646,0x1d61d7f8,0x1ddb56d8,0x1e59a281,0x1edf03d3,0x1f66d255,0x1fe26f82,0x205ec456,0x20d2bded, //2019 0x21484431,0x21c24ba6,0x2230c76f,0x22a6cd0e,0x2312ebbd,0x23844c83,0x23f45e42,0x246d38c1,0x24eb9338,0x255dc81a,0x25d30c39,0x264389a4, //2020 0x26b9cb56,0x2730f2c2,0x279824a7,0x28072e59,0x2870b46c,0x28e20cee,0x294ea8da,0x29bdfadb,0x2a2f2276,0x2a987389,0x2b026a37,0x2b6628b7, //2021 0x2bcd3a33,0x2c3819e9,0x2c95c80f,0x2cf681ad,0x2d57afa7,0x2dc0df59,0x2e283430,0x2e94df63,0x2f016036,0x2f63046c,0x2fc3e3be,0x301fada4, //2022 0x307f54f1,0x30e474f9,0x313bba85,0x3199f875,0x31f91c99,0x3259674f,0x32b90ef5,0x3320eb2e,0x3386b446,0x33e58f10,0x34460066,0x34a0858b, //2023 0x35000bf5,0x355fc5bf,0x35b7d331,0x36103eca,0x3672d063,0x36d1e7fb,0x372dee4d,0x378d05e6,0x37ec1d7e,0x384823d0,0x38a75c21,0x39036272, //2024 0x39627a0b,0x39c191a3,0x3a177567,0x3a766c47,0x3ad27299,0x3b318a32,0x3b8d9083,0x3beca81c,0x3c4bbfb4,0x3ca7c606,0x3d06fe57,0x3d6304a9, //2025 0xffffffff]; function uploadDate(imgName) { const monthYearIndex = (element) => element >= parseInt(imgName, 16); let index = imgTable.findIndex(monthYearIndex) - 1; let year = 2003 + Math.trunc(index / 12); let month = 1 + index % 12; if (imgTable[index] == 0x00000000) { return ''; } else { return `≈ ${month}.${year}${imgTable[index + 1] == 0xffffffff ? '+' : ''}`; } } // ***** Copy message thread to clipboard ***** function copyMessageThread(profileId, profileName) { let loadTime = new Date().toLocaleString('de-DE').slice(0,-3); let ownName = 'unknown'; let msgThread = '- keine Nachrichten -'; let msgCount = '', header = '', msgTime = '', name = ''; $.ajax({headers: ajaxHead(), url: `/api/v4/session?lang=de`}).done(function (data) { if (data.username) { ownName = data.username; } let jsonParam = `lang=de&length=10000&filter[folders][]=SENT&filter[folders][]=RECEIVED&filter[partner_id]=${profileId}`; $.ajax({headers: ajaxHead(), url: `/api/v4/messages?${jsonParam}`}) .done(function (data) { //gather data header = 'Nachrichtenverlauf von ' + ownName + ' mit ' + profileName + ' (Profil-ID ' + profileId + ') vom ' + loadTime + '\n\n\n'; if (data.items_total) { msgThread = ''; msgCount = data.items_total; for (let i = msgCount-1; i >= 0; i--) { msgTime = new Date(data.items[i].date.slice(0,-5)+'.000Z'); name = (data.items[i].folder == 'SENT') ? ownName : profileName; msgThread += msgCount-i + '. ' + name + ' • ' + msgTime.toLocaleString('de-DE').slice(0,-3); msgThread += (data.items[i].unread == true) ? ' [ungelesen]' : ''; msgThread += (data.items[i].locked == true) ? ' [gespeichert]' : ''; msgThread += (data.items[i].spam == true) ? ' [Spam]' : ''; msgThread += '\n-------------------------------------------------------------------'; msgThread += '\n' + data.items[i].text.trim() + '\n\n\n'; //handle links if (data.items[i].attachments) { for (let item of data.items[i].attachments) { if (item.type == 'COMMAND') { msgThread += `[${item.index + 1}] ${item.params?.url?.match(/^\//) ? 'https://www.romeo.com' : ''}${item.params?.url}\n`; msgThread = msgThread.replace(`[[${item.index}]]`, `${item.params?.text} [${item.index + 1}]`); } } msgThread += '\n\n' } } msgThread += '\n====================\n\n'; } //confirm copy $('div.js-correspondence').after( `<div class="re-bubble layout layout--h-center"> <div class="ui-bubble ui-bubble--dark" style="width:auto; top:72px"> <div class="ui-bubble__content [ js-content ] [ js-scrollable ] scrollable"> <div class="confirm-box"> <div class="txt-right" style="margin:-.5rem -.5rem -.75rem"> <a class="re-copy-cancel re-link icon icon-larger icon-cross"></a> </div> <div class="confirm-box__label" style="margin-bottom:1.125rem"> <p>Nachrichtenverlauf kopieren</p> </div> <div class="confirm-box__actions"> <button class="re-copy-email ui-button ui-button--transparent">E-Mail-Entwurf</button> <button class="re-copy-confirm ui-button ui-button--primary">Zwischenablage</button> </div> </div> </div> </div> </div> <div class="layer ui-bubble__overlay l-fancy"></div>` ); $('button.re-copy-confirm').focus().click(function() { navigator.clipboard.writeText(header + msgThread); $('div.re-bubble, div.ui-bubble__overlay').hide(); }); $('button.re-copy-email').click(function() { location.href = `mailto:?subject=${encodeURIComponent(header)}&body=${encodeURIComponent(msgThread)}`; $('div.re-bubble, div.ui-bubble__overlay').hide(); }); $('a.re-copy-cancel, div.ui-bubble__overlay').click(function() { $('div.re-bubble, div.ui-bubble__overlay').hide(); }); }); }); } // ***** Fix scrolling on larger screens for messages list ***** function fixScroll (jNode) { $(jNode).parents('.js-chat .js-scrollable').attr('style', 'max-height:inherit !important'); } // ***** Add double tap to menu items, change behavior for mobile ***** function handleMainMenu (jNode) { if (!mobile.matches) { // $(jNode).has('path[d^="M13.493"]').off().has('p[class^="SpecialText"]').click(function() { changeUrl('/messenger/chat'); return false; }); // $(jNode).filter('a[href^="/messenger"]').attr('style', 'pointer-events:auto').filter('a[isactive="true"]').off().click(function() { $('#messenger').addClass('is-hidden'); return false; }); // $(jNode).has('path[d^="M6.99 10"]').off().click(function() { changeUrl('/groups/discover'); return false; }); $(jNode).has('path[d^="M6.99 10"]').find('button').off('click').click(function() { if (lastGroupName && sessionStorage.getItem('PR_SETTINGS:cachedNavTab')?.match('"groups":"member"')) { changeUrl(`/groups/member/${lastGroupName}`); return false; } else { return true; } }); } else { $(jNode).has('path[d^="M20.3943"], path[d^="m20.507"]').off('dblclick').dblclick(function() { changeUrl('/stream'); return false; }); $(jNode).has('path[d^="M23.102"]').off('dblclick').dblclick(function() { changeUrl('/visitors/me'); setSessionStorageItem('PR_SETTINGS:cachedNavTab', 'visitors', 'me'); return false; }); $(jNode).has('path[d^="M13.493"]').off('dblclick').dblclick(function() { changeUrl('/messenger/contacts'); setSessionStorageItem('PR_SETTINGS:cachedNavTab', 'messenger', 'contacts'); return false; }); $(jNode).has('path[d^="M6.99 10"]').off('click').click(function() { changeUrl('/groups/member'); return false; }); } } // ***** Add contacts etc. to tab navigation ***** function handleTabMenu (jNode) { //icons on radar and eyecandy if (!mobile.matches) { $('main nav.js-navigation ul').has('a[href^="/radar/"], a[href^="/eyecandy/"]').not(':has(li.re-add > span)').append( '<li class="Tabbed-nav-item--TCdwx re-add"><span class="re-add re-radar-travel icon icon-airplane" title="Reiseziel"><span></span></span></li>' ); $('main nav.js-navigation ul').has('a[href^="/radar/"], a[href^="/eyecandy/"], a[href^="/hunqz"]').not(':has(li.re-add > a)').append( '<li class="Tabbed-nav-item--TCdwx re-add"><a style="cursor:default">|</a></li>' + '<li class="Tabbed-nav-item--TCdwx re-add"><a href="/messenger/contacts" class="js-nav-item Tabbed-nav-link--x9FLb" title="Kontakte"><span class="icon icon-save-contact"></span></a></li>' + `<li class="Tabbed-nav-item--TCdwx re-groups-icon re-add"><a href="" class="js-nav-item Tabbed-nav-link--x9FLb" title="Meine Gruppen (${lastGroupName})"><span class="icon icon-group-members"></span></a></li>` ); $('.re-groups-icon a').off('click').click(function() { (async() => { while (!lastGroupName) await new Promise(resolve => setTimeout(resolve, 300)); changeUrl(`${(lastGroupName) ? `/groups/member/${lastGroupName}` : `/groups/member`}`); setSessionStorageItem('PR_SETTINGS:cachedNavTab', 'groups', 'member'); })(); return false; }); //fix for phantom filter in eyecandy $('main nav.js-navigation ul').has('a[href^="/eyecandy/"]').closest('.is-filter-opened').removeClass('is-filter-opened'); } else { $('main nav.js-navigation ul').has('a[href^="/radar/"], a[href^="/eyecandy/"]').not(':has(li.re-add)').prepend( '<li class="Tabbed-nav-item--TCdwx re-add"><span class="re-add re-radar-travel icon icon-airplane" title="Reiseziel"><span></span></span></li>' ); } //travel if ($('main nav.js-navigation ul').has('a[href^="/radar/"], a[href^="/eyecandy/"]').length) { let viewMode = localStorage.getItem('REradarTravelLocation'); let toggleTravel = 'span.re-radar-travel'; handleTravelLocation(viewMode, toggleTravel); $('span.re-radar-travel').off().click(function() { let viewMode = localStorage.getItem('REradarTravelLocation'); let toggleTravel = 'span.re-radar-travel'; let refreshClick = 'li.Tabbed-nav-item--TCdwx a.is-selected'; viewMode = (viewMode == 'travel') ? 'default' : 'travel'; localStorage.setItem('REradarTravelLocation', viewMode); handleTravelLocation(viewMode, toggleTravel, refreshClick); }); } //icons on groups if (!mobile.matches) { $('div.js-navigation ul').has('a[href="/groups/discover"]').not(':has(li.re-add)').append( '<li class="Tabbed-nav-item--TCdwx re-add"><a style="cursor:default">|</a></li>' + '<li class="Tabbed-nav-item--TCdwx re-add"><a href="/messenger/contacts" class="js-nav-item Tabbed-nav-link--x9FLb" title="Kontakte"><span class="icon icon-save-contact"></span></a></li>' ); } $('div.js-navigation ul li').not('.re-add').find('a[href="/groups/member"]').titleLabel(`${commonGroupsList.length.toLocaleString()} Gruppen abonniert`); //remove GR-Tools hint $('li.re-grtools').remove(); } // ***** Show versions and users online in main menu ***** function handleVersion (jNode) { $(jNode).addClass('re-done'); let reVersion = `${(typeof GM_info !== 'undefined') ? `${GM_info.script.name} ${GM_info.script.version}` : 'RomeoEnhancer'}`; let onlineAll = ''; $.ajax({url: `/api/services/landing/online-count`}) .done(function (data) { onlineAll = `${data.online_count?.toLocaleString()} Profile online`; $(jNode).find('.re-add').remove(); $(jNode).append(`<div class="txt-preserve re-add">${reVersion}\n${onlineAll}</div>`); let profileType = ($('li.is-selected, li[class*="list__item--active"]').find('a[href*="/hunqz"]').length) ? '/hunqz/profiles' : '/profiles'; let users = '', online = ''; $.ajax({headers: ajaxHead(), url: `/api/v4${profileType}?pick=items_total&lang=de&length=1`}).done(function (data) { users = `${data.items_total?.toLocaleString()} User`; $.ajax({headers: ajaxHead(), url: `/api/v4${profileType}?pick=items_total&lang=de&length=1&filter[online_status][]=ONLINE&filter[online_status][]=DATE&filter[online_status][]=SEX`}).done(function (data) { online = `${data.items_total?.toLocaleString()} online`; $(jNode).off().on('dblclick', function() { $(jNode).find('div').replaceWith(`<div class="txt-preserve re-add">${reVersion}\n${onlineAll}\n${users} • ${online}</div>`); }); }); }); }); //display /*if (location.pathname == '/me/display') { console.log('Display menu'); $('#offcanvas-nav div.settings__key:first-child').not('.re-add').clone().insertBefore('#offcanvas-nav div.settings__key:first-child').first().addClass('re-add'); }*/ } // ***** Show selected bookmark in filter icon title and text ***** function handleBookmark (jNode) { // console.log('handleBookmark'); let selectedBookmark = $('div[class^="js-bookmarks-list"] div[class*="item__is-selected"] a').text().trim(); if (selectedBookmark) { $('div.js-filter-button button').attr('style', 'color:rgb(250,250,250); background-color:transparent'); $('div.js-filter-button button title').text(`Lesezeichen: ${selectedBookmark}`); $('div.js-filter-button button span').not('.re-add').addClass('re-filter-options-text'); $('div.js-filter-button button').not(':has(.re-add)').append(`<span class="re-add re-filter-bookmark-name mr">${selectedBookmark}</span>`); $('div.js-filter-button button span').attr('title', `Lesezeichen: ${selectedBookmark}`); //$('nav.js-navigation li.js-filter-button div.js-filter-button button').attr('title', `Lesezeichen: ${selectedBookmark}`); $('button.ui-navbar__button--bookmarks').attr('title', 'Lesezeichen auswählen'); } else { $('div.js-filter-button button span.re-filter-options-text').removeClass('re-filter-options-text'); $('div.js-filter-button button span.re-add').remove(); } } // ***** Preview unread messages in title tag, delete by clicking blue badge ***** function previewMessage (jNode) { $(jNode).addClass('re-done'); let profileId = $(jNode).closest('a').attr('href').match(/\d{3,}/); if (profileId) { $(jNode).closest('a').addClass('re-id' + profileId); let msgCount = parseInt($(jNode).text()); let jsonParam = 'lang=de&length=' + msgCount + '&filter[folders][]=RECEIVED&filter[partner_id]=' + profileId; let msgText = ''; let thisId = '.re-id' + profileId; $.ajax({headers: ajaxHead(), url: '/api/v4/messages?' + jsonParam}).done(function (data) { //preview for (let i = msgCount-1; i >= 0; i--) { msgText += '\r' + data.items[i].text + '\r'; //handle links if (data.items[i].attachments) { for (let item of data.items[i].attachments) { if (item.type == 'COMMAND') { // console.log('attachments COMMAND'); msgText = msgText.replace(`[[${item.index}]]`, `[${item.params?.text}]`); } } } } $(thisId).attr('title', msgText); $(thisId).find('img').parent('div').attr('title', msgText); //delete unread $(jNode).parent('div').wrap(`<div style="margin:-.5rem; padding:.5rem; ${(touch.matches) ? 'margin:0 0 -.5rem -.5rem' : ''}"></div>`).parent().attr('title', 'Löschen').off().click(function () { if (confirm(msgCount + ' Nachrichten ungelesen löschen?')) { for (let i = msgCount-1; i >= 0; i--) { $.ajax({url: '/api/v4/messages/' + data.items[i].id + '?expand=from', headers: ajaxHead(), method: 'DELETE' }) .done(function (data) { $(jNode).closest('a[href^="/messenger/chat"]').attr('title', 'Liste aktualisieren').off().click(function() { $('#messenger .js-navigation a.is-selected')[0].click(); return false; }).children('div').replaceWith( `<div style="font-size:.925rem;color:rgba(255,255,255,.8)">– ungelesen gelöscht –</div>` ); }) } } return false; }) }); //highlight profile name $(jNode).closest('a').find('p[class^="BodyText"]').attr('style', 'color:rgba(255,255,255,1); opacity:1'); } } // ***** Show last login and location in message thread ***** function showLoginLocation (jNode) { //placeholder for login and location $('section.js-detail > div').not(':has(.re-login-location)').append( `<div class="re-login-location re-add"></div>` ); if ($('.js-correspondence > div').filter('.re-add').length) return; let profileId = location.pathname.match(/\d{3,}$/); let name = '', country = '', distance = '', sensor = ''; let loginTime = '', loginLocalTime = '', timeTag = '', lastSince = '', offlineSince =''; $.ajax({headers: ajaxHead(), url: `/api/v4/profiles/${profileId}?expand=partner&lang=de`}) .done(function (data) { $('.js-correspondence > div').addClass('re-add'); //last login if (data.last_login && data.online_status) { loginTime = new Date(data.last_login.slice(0,-5)+'.000Z'); loginLocalTime = dateTime(loginTime); timeTag = dateTime(loginTime, !mobile.matches); lastSince = `${data.online_status == 'OFFLINE' ? 'Zuletzt online:' : 'Online seit:'}`; if (($(jNode).closest('div').parent().find('[class*="OnlineStatus"]')).length == 0) { offlineSince = `<span class="icon icon-last-login-hours mr-- re-add" style="font-size:.75rem; color:rgba(250,250,250,.75)" title="${lastSince} ${loginLocalTime}"> ${touch.matches ? '' : timeTag}</span>`; }; } //location, distance if (data.location?.name) { name = `<a class="re-link-idle" target="_blank" href="https://google.com/maps/place/${data.location.name}" rel="noreferrer noopener" title="Ort in Google Maps anzeigen">${data.location.name.trim()}</a>`; } if (data.location?.country && (data.location?.distance > 50000 || data.location?.distance == null)) { country = `, ${data.location.country}`; } if (data.location?.distance >= 0) { if (data.location.distance < 1000) { distance = ' • ' + data.location.distance + 'm'; } else if (data.location.distance < 50000) { distance = ' • ' + (Math.round(data.location.distance/100)/10).toLocaleString() + ' km'; } else { distance = ' • ' + (Math.round(data.location.distance/1000)) + ' km'; } } if (data.location?.sensor) { sensor = '<span class="icon icon-gps-needle icon-badge mr-" style="font-size:.85em"></span>'; } }) .always(function (data) { $('section.js-detail div.re-login-location').html(` <div class="re-msg-location">${sensor}${name}${country}${distance}</div> <div class="re-msg-login" title="${lastSince} ${loginLocalTime}"> <span class="re-touch">${lastSince} ${loginLocalTime}</span></div> <div class="re-msg-offline">${offlineSince}</div>` ); }); } // ***** Add copy to message thread options menu ***** function threadOptionsMenu (jNode) { $(jNode).find('li').first().not('.re-done').addClass('re-done').clone().appendTo($(jNode)).click(function() { let profileId = '', profileName = ''; if ($(this).closest('#messenger').length) { profileId = location.pathname.match(/\d{3,}/); profileName = $('#messenger div.js-correspondence').find('a > p[class^="BodyText"]').first().text().trim(); } else { profileId = xhrFull.id; profileName = xhrFull.name; } copyMessageThread(profileId, profileName); return false; }).attr('id', 'options_copy').find('span').text('Kopieren'); } // ***** Zoom footprints list ***** //init let setFootprintZoom = (localStorage.getItem('REfootprintZoom') === 'true'); function handleFootprints (jNode) { setFootprintZoom ? $('.js-profile-footprints').addClass('re-zoom') : $('.js-profile-footprints').removeClass('re-zoom'); $('.js-profile-footprints h1 > span').last().not(':has(.re-add)').wrapInner( `<a class="re-link mr re-add" style="font-size:1.2rem" title="Vergrößern" href="">- +</a>` ).click(function() { setFootprintZoom = !setFootprintZoom; localStorage.setItem('REfootprintZoom', setFootprintZoom); $('.js-profile-footprints').toggleClass('re-zoom'); return false; }); } // ***** Filter by "no entry" ***** function handleFilterNoEntry (jNode) { //insert button $(jNode).not('.re-add').addClass('re-add').after(` <div class="re-add layout mt mh++"> <a class="re-button-no-entry ui-tag ui-tag--center" href="">+ keine Angabe <span class="icon icon-small icon-info ml-" title="Zeigt auch Profile, die zu den ausgewählten Filterkategorien keine Angabe enthalten" aria-label="Zeigt auch Profile, die zu den ausgewählten Filterkategorien keine Angabe enthalten"></span> </a> </div>` ).next('div.re-add').off().click(function() { filterNoEntry = !filterNoEntry; localStorage.setItem('REfilterNoEntry', filterNoEntry); //toggle button $('.re-button-no-entry').toggleClass('ui-tag--selected'); //reload radar tab $('section.js-main-stage div.js-navigation').find('a.is-selected, div.js-nav-item').get(0).click(); return false; }); if (filterNoEntry) $('.re-button-no-entry').addClass('ui-tag--selected'); } // ***** Link contact icons in messages list entries ***** function handleMessage (jNode) { let profileId = new Array; profileId = $(jNode).attr('href').match(/\d{3,}/); if (! profileId) profileId = location.pathname.match(/\d{3,}/); $(jNode).not(':has(a.re-add)').find('svg').has('path[d^="M4 8a4"]').wrap( `<a href="/messenger/contacts/all/${profileId}" class="re-add"></a>` ); $(jNode).not(':has(a.re-add)').find('svg').has('path[d^="M8.039"]').wrap( `<a href="/messenger/contacts/blocked/${profileId}" class="re-add"></a>` ); $(jNode).find('span > div > p[class^="SpecialText"]:contains("Gelesen")').text('Gelesen ✓'); } // ***** Open links in messages without opening flyout menu ***** function handleMessageLink (jNode) { $(jNode).off().click(function() { (this.target) ? window.open(this.href, this.target, this.rel) : changeUrl(this.href); return false; }); } // ***** Scroll to last message in thread ***** function handleMessageScroll (jNode) { $(jNode).addClass('re-done'); // console.log('scrollIntoView'); $('#messages-list .message__content').last()[0].scrollIntoView({block: 'start'}); } // ***** Add message icons to contact list entries ***** function handleContacts (jNode) { let profileId = new Array; profileId = $(jNode).attr('href').match(/\d{3,}$/); if (! profileId) profileId = location.pathname.match(/\d{3,}$/); $(jNode).find('p[class^="BodyText-"] > span, span > span').last().not(':has(a)').prepend( `<a class="icon icon-chat re-icon re-idle ml-- mr-" title="Messages" href="/messenger/chat/${profileId}"></a>` ); } // ***** Prompt for removing contacts tags ***** function handleTagRemove (jNode) { $(jNode).titleLabel('Löschen').off().click(function() { return confirm(`»${$(this).prev().text().trim()}« löschen? \rAlle Zuweisungen zu Kontakten gehen verloren.`); }); } // ***** Link user names on discover page to messages ***** function handleContactStrip (jNode) { let replacePattern = /(.*\/(profile|hunq|group)\/)([-\w]*)(.*)/; let profileLink = $(jNode).attr('href'); $(jNode).attr('href', profileLink.replace(/\/group\//, '/profile/')); let profileName = profileLink.replace(replacePattern, '$3'); let baseUrl = '/messenger/chat/'; $(jNode).find('div[class^="Name-"]').attr('title', profileName)/*.wrapInner( `<a class="re-link-idle" title="${profileName} | Messages" href="${baseUrl}${profileName}"></a>` ).children()*/.off().click(function() { openByName(baseUrl, profileLink, profileName); return false; }).attr('style', `${profileLink.match(/^\/hunq\//) ? 'color:#fc193c' : ''}`); } // ***** Mark common groups ***** function handleGroupTiles (jNode) { $(jNode).addClass('re-done'); (async() => { while (! commonGroupsLoaded) await new Promise(resolve => setTimeout(resolve, 300)); // console.log('handleGroupTiles'); let jNodeGroupTiles = $(jNode).closest('a'); if (jNodeGroupTiles.attr('href')?.match(/^\/group\//)) { const profileName = jNodeGroupTiles.attr('href').match(/[-\w]+$/); const nameIndex = (item) => item.name == profileName; if (commonGroupsList.findIndex(nameIndex) > -1) { jNodeGroupTiles.addClass('re-common-group'); jNodeGroupTiles.find('p').last().attr('title', 'Du bist Mitglied in dieser Gruppe'); } //show full group name in title jNodeGroupTiles.find('p').first().attr('title', $(jNode).find('p').first().text().trim()); } })(); } // ***** Sort EyeCandy on startpage by Nearby or Activity ***** function handleDiscoverEyecandy (jNode) { $(jNode).not('.re-done').addClass('re-done').append(` <a class="re-link re-eyecandy-active ml" title="Umschalten" href=""> <span>${$('a[href^="/radar/distance"]').first().text().trim()}</span> <span>${$('a[href^="/radar/login"]').first().text().trim()}</span> <svg aria-hidden="true" viewBox="0 0 10 6" height="6" width="10"> <path fill-rule="evenodd" d="M5.707 5.707a1 1 0 0 1-1.414 0l-4-4A1 1 0 0 1 1.707.293L5 3.586 8.293.293a1 1 0 0 1 1.414 1.414l-4 4Z" clip-rule="evenodd"></path> </svg> </a>` ).children().off().click(function() { eyecandyActive = !eyecandyActive; localStorage.setItem('REeyecandyActive', eyecandyActive); $('.re-eyecandy-active').toggleClass('is-selected'); $('li[class^="Tabbed-nav-item-"] a.is-selected')[0].click(); return false; }); if (eyecandyActive) $('.re-eyecandy-active').addClass('is-selected'); } // ***** Add message icons to discover, radar, visitor list, search results, and group member list, link contact icons ***** function handleTiles (jNode) { let jNodeTiles = $(jNode).closest('a, button'); let profileName = $(jNode).text().trim(); let profileLink = `/${(location.pathname.match(/^\/hunqz\//) ? 'hunq' : 'profile')}/${profileName}`; //add + to distance if travel if ((travelMode && location.pathname.match(/^\/(radar|groups|eyecandy)\//)) || location.pathname.match(/^\/explore\//) || $('.ui-navbar').has('path[d^="M6 8c-1"]').length) { if (jNodeTiles.find('svg + p[class^="SpecialText"]').not('.re-add').text().match(/(\d[\d\.,]*\s?(km|m|mi|ft))/)) { let distance = `+${jNodeTiles.find('svg + p[class^="SpecialText"]').html()}`; jNodeTiles.find('svg + p[class^="SpecialText"]').html(distance).addClass('re-add'); } } //add visit icons let visitReceivedTime, visitMadeTime = '', index = -1; const nameIndex = (item) => item.name == profileName; (async() => { while (! (visitorsLoaded && visitsLoaded)) await new Promise(resolve => setTimeout(resolve, 300)); // console.log('visitors await'); index = visitorsList.findIndex(nameIndex); if (index >= 0) visitReceivedTime = new Date(visitorsList[index].date_visited); index = visitsList.findIndex(nameIndex); if (index >= 0) visitMadeTime = new Date(visitsList[index].date_visited); //visits made page if ($(jNode).closest('#visits-made:not(is-hidden)').length && ! $(jNode).closest('#visits-received:not(is-hidden)').length) { if (visitReceivedTime) { $(jNode).parent().parent().children().first().not(':has(.icon-visitor)').append( `<a class="icon icon-visitor re-icon re-icon-visitor ml-" title="Hat mich besucht: ${weekTime(visitReceivedTime)}" href="/visitors"></a>` ); } if ($(jNodeTiles).find('time').length) $(jNodeTiles).find('time').text(weekTime(visitMadeTime)).attr('title', weekTime(visitMadeTime)); //other } else { if (visitMadeTime) { $(jNode).parent().parent().children().first().not(':has(.icon-visitor)').append( `<a class="icon icon-visitor re-icon re-icon-visited ml-" title="Von mir besucht: ${weekTime(visitMadeTime)}" href="/visitors/me"></a>` ); } if ($(jNodeTiles).find('time').length) $(jNodeTiles).find('time').text(weekTime(visitReceivedTime)).attr('title', weekTime(visitReceivedTime)); } })(); //link username in list view if ($(jNode).closest('button').length) { $(jNode).not(':has(.re-link-idle)').wrapInner( `<a class="re-link-idle" title="${profileName}" href="${profileLink}"></a>` ).off().click(function() { changeUrl(`${profileLink}`); return false; }); } //add message icon let baseUrl = '/messenger/chat/'; $(jNode).parent().not(':has(.icon-chat)').append( `<a class="icon icon-chat re-icon re-idle ml-" title="Messages" href="${baseUrl}${profileName}"></a>` ).children().last().click(function() { openByName(baseUrl, profileLink, profileName); return false; }); //link contact icon jNodeTiles.find('svg').has('path[d^="M4 8a4"]').not('.re-contact').addClass('re-contact').wrap( `<a class="re-idle-no-hover re-contact" title="Kontakt bearbeiten" href="/messenger/contacts/all/${profileName}"></a>` ); jNodeTiles.find('a.re-contact').off().click(function() { openByName('/messenger/contacts/all/', profileLink, profileName); // console.log(profileLink, profileName); return false; }); jNodeTiles.find('svg').has('path[d^="M8.039"]').not('.re-contact-blocked').addClass('re-contact-blocked').wrap( `<a class="re-idle-no-hover re-contact-blocked" title="Kontakt bearbeiten" href="/messenger/contacts/blocked/${profileName}"></a>` ); jNodeTiles.find('a.re-contact-blocked').off().click(function() { openByName('/messenger/contacts/blocked/', profileLink, profileName); return false; }); //only in radar, travel, hunqz, eyecandy if ($(jNode).closest('#profiles').length) { // console.log('radar'); //link username to preview $(jNode).not(':has(.re-link-idle)').wrapInner( `<a class="re-link-idle" title="${profileName} | Vorschau" href="${profileLink}"></a>` ).off().click(function() { changeUrl(`${profileLink}/preview`); return false; }); } //only for last tile in radar, travel, hunqz, eyecandy if ($(jNode).closest('#profiles').length && !$(jNode).closest('div.search-results__item').next('div.search-results__item').length) { // console.log('radar stats'); //show count of profiles, Plus, travelling, and GPS in title tag of selected tab let loadTime = new Date().toLocaleTimeString() + ' aktualisiert'; let profiles = $('#profiles :is(div.BIG, div.SMALL, div.LIST)').length; let profilesPlus = ''; let percentPlus = ''; if ($('#profiles .search-results--mixed-tiles').length) { profilesPlus = $('#profiles .search-results--mixed-tiles div.tile--plus, #profiles .search-results--big-tiles').length; percentPlus = (profiles > 0 ? ' (' + (Math.round(profilesPlus/profiles*1000)/10).toLocaleString() + ' %)' : ''); profilesPlus = ' • ' + profilesPlus + ' Plus' + percentPlus; } let profilesTravel = ''; let percentTravel = ''; profilesTravel = $('#profiles svg > path[d^="M10.0452"]').length; percentTravel = (profiles > 0 ? ' (' + (Math.round(profilesTravel/profiles*1000)/10).toLocaleString() + ' %)' : ''); profilesTravel = `${profilesTravel} ${(profilesTravel == 1 ? 'Reisender' : 'Reisende')}${percentTravel}`; let profilesGPS = ''; let percentGPS = ''; profilesGPS = $('#profiles svg > path[d^="M11.94"]').length; percentGPS = (profiles > 0 ? ' (' + (Math.round(profilesGPS/profiles*1000)/10).toLocaleString() + ' %)' : ''); profilesGPS = ' • ' + profilesGPS + ' GPS' + percentGPS; profiles += ` ${(profiles == 1 ? 'Profil' : 'Profile')} geladen`; $('ul[class^="Tabbed-nav--"] li.is-selected, ul[class^="list--"] li[class*="list__item--active--"], div.js-nav-item').attr( 'title', `${loadTime}\r${profiles}${profilesPlus}\r${profilesTravel}${profilesGPS}` ); } } // ***** Add message icons to non-message Activity Stream entries; handle group related entries; add icon to settings ***** function handleStream (jNode) { let jNodeStream = $(jNode).closest('a'); let bodyLink = jNodeStream.attr('href'); let profileLink = '', profileName = ''; let baseUrl = '/messenger/chat/'; if (bodyLink != undefined) { let replacePattern = /(.*\/(profile|hunq|groups)\/)([-\w]*)(.*)/; profileLink = jNodeStream.parent().find('a').attr('href'); profileName = profileLink.replace(replacePattern, '$3'); //link contact icon jNodeStream.find('svg').has('path[d^="M4 8a4"]').not('.re-contact').addClass('re-contact').wrap( `<a class="re-idle-no-hover re-contact" title="Kontakt bearbeiten" href="/messenger/contacts/all/${profileName}"></a>` ); jNodeStream.find('a.re-contact').off().click(function() { openByName('/messenger/contacts/all/', profileLink, profileName); return false; }); jNodeStream.find('svg').has('path[d^="M8.039"]').not('.re-contact-blocked').addClass('re-contact-blocked').wrap( `<a class="re-idle-no-hover re-contact-blocked" title="Kontakt bearbeiten" href="/messenger/contacts/blocked/${profileName}"></a>` ); jNodeStream.find('a.re-contact-blocked').off().click(function() { openByName('/messenger/contacts/blocked/', profileLink, profileName); return false; }); } if (bodyLink != undefined && ! bodyLink.match('/messenger/chat/')) { //add message icon if (profileName) { jNodeStream.find('p[class^="BodyText-"]').not(':has(a,img)').prepend( `<a class="icon icon-chat re-icon mr-" title="Messages" href="${baseUrl}${profileName}"></a>` ).children().last().click(function() { openByName(baseUrl, profileLink, profileName); return false; }); } //italic if system text jNodeStream.find('span.listitem__text').not('.thumbnail__info').attr('style', 'font-style:italic'); //decode html entities in group names let msgText = jNodeStream.find('span.listitem__text').not('.thumbnail__info').text().trim(); jNodeStream.find('span.listitem__text').not('.thumbnail__info').html(msgText); //add icon if group picture, hide group pictures in small stream let jNodeGroupPicture = jNodeStream.has('img.thumbnail').not(':has(span.icon-heart, span.icon-camera-icon, .re-add)'); jNodeGroupPicture.find('span.listitem__timestamp').after( `<span class="clr-ui-text listitem__highlight--expanded re-add"><span class="icon icon-group-members"></span></span>` ); if (! location.pathname.match(/^\/stream/)) { /*jNodeGroupPicture.find('span.listitem__text').first().hide(); jNodeGroupPicture.attr('title', jNodeGroupPicture.find('span.listitem__text').first().text().trim()); $(jNodeGroupPicture).parent().addClass('re-group-item');*/ $(jNodeGroupPicture).parent().addClass('re-group-item').hide(); } else { //hide group pictures of blocked users $(jNodeGroupPicture).has('path[d^="M8.039"]').parent().addClass('re-group-item').hide(); } } //add enlarge and settings $('div.stream__content div.js-list').not(':has(div.re-add)').prepend(` <div class="re-add mt-- mb- mh" style="display:flex; justify-content:space-between; align-items:center; height:.875rem"> <div class="layout">${(!location.pathname.match(/^\/stream$/)) ? `<a href="/stream" class="icon icon-back re-icon re-link p0 re-stream-group-items" title="Erweitern"></a>` : ``}</div> <a href="/me/notifications" class="icon icon-settings re-icon re-link p0"><span class="ml--">Anpassen</span></a> </div>` ); let groupItems = $('section.js-stream .re-group-item').not(':has(path[d^="M8.039"])').length; if (groupItems) { $('.re-stream-group-items').html(`<span class="ml-">${groupItems}<span class="icon icon-group-members" style="margin-left:.15rem"></span></span>`).attr('title', `Erweitern • Neue Bilder in ${groupItems} Gruppe${(groupItems == 1) ? '' : 'n'}`); } } // ***** Profiles: show profile id, visits since; link URLs ***** function handleProfile (jNode) { let profileName = $('div.top-info-header p[class^="BodyText"]').first().text().trim(); let profileType = ($('div.is-profile-loaded').hasClass('profile--hunqz')) ? '/hunqz/profiles' : '/profiles'; let profilePath = ($('div.is-profile-loaded').hasClass('profile--hunqz')) ? 'hunq' : 'profile'; let profileId = '', profileIdInfo = '', visits = '', since = '', known = '', known1st = '', known2nd = '', verified = ''; let albums = 0, profilePictures = 0, albumPictures = 0, quickSharePictures = 0; let name = '', country = '', distance = ''; let loginTime = '', loginLocalTime = '', timeTag = '', lastSince =''; let sinceMonthYear = $('section.profile__stats section > p').last().contents().filter(function(){ return this.TEXT_NODE; }).first().text(); let data = xhrFull; if (data.id) { profileId = data.id; profileIdInfo = `Profil-ID: ${data.id}`; } if (data.visits_count) { // not 0 or undefined visits = `<br>Besucher: ${data.visits_count.toLocaleString()}`; } if (data.creation_date) { since = new Date(data.creation_date.slice(0,-5)+'.000Z').toLocaleDateString(); since = 'Mitglied seit: ' + since; } else { since = sinceMonthYear; } //known by if (data.known_by && data.known_by.first_degree > 0) { known1st = data.known_by.first_degree; known2nd = data.known_by.second_degree; known = `Bekannt bei ${known1st.toLocaleString()} ${known1st == 1 ? 'Nutzer (dieser' : 'Nutzern (diese'} bekannt bei ${known2nd.toLocaleString()})`; } else { known = `Noch nicht bei anderen bekannt`; } //online time if (data.last_login && data.online_status) { loginTime = new Date(data.last_login.slice(0,-5)+'.000Z'); loginLocalTime = dateTime(loginTime); timeTag = dateTime(loginTime, 'dateOnly'); lastSince = `${data.online_status == 'OFFLINE' ? 'Zuletzt online:' : 'Online seit:'}`; } //show pictures count if (data.albumsV2.items_total) { for (let item of data.albumsV2.items) { if (item.id == 'PROFILE') { if (item.pictures) { profilePictures += item.pictures.items_total; } } else if (item.access_policy == 'SHARED') { quickSharePictures += item.items_total; } else { if (item.pictures) { albumPictures += item.pictures.items_total; //albums += (item.items_total) ? 1 : 0; } } } if (profilePictures > 1) { $('section.profile__image-strip').not(':has(.re-add)').append( `<div class="re-add re-img-count"><div><p>${profilePictures}</p></div></div>` ).children().last().click(function(){ changeUrl(`/${profilePath}/${profileName}/gallery`); }).attr('style', 'cursor:pointer').titleLabel('Alle Alben anzeigen'); } if (quickSharePictures) { $('section.js-profile-stats section > div > a > div > div').first().has('svg').not(':has(.re-add)').append( `<div class="re-add re-img-count"><div><p>${quickSharePictures}</p></div></div>` ); } if (quickSharePictures || albumPictures) { $('section.profile__stats section > div[class^="InfoText-"] p[class^="BaseText"]').first().not(':has(.re-add)').append( `<span class="re-add" style="font-size:.925em; color:rgba(255,255,255,.6)"> • ${quickSharePictures + albumPictures} Bilder</span>` ); } } //link location name to maps if (data.location.name) { name = `<a target="_blank" href="https://google.com/maps/place/${data.location.name}" rel="noreferrer noopener" class="re-link-idle" title="Ort in Google Maps anzeigen">${data.location.name.trim()}</a>`; } if (data.location.country && (data.location.distance > 50000 || data.location.distance == null)) { country = `, ${data.location.country}`; } if (data.location.distance != null) { if (data.location.distance < 1000) { distance = ' • ' + data.location.distance + 'm'; } else if (data.location.distance < 50000) { distance = ' • ' + (Math.round(data.location.distance/100)/10).toLocaleString() + ' km'; } else { distance = ' • ' + (Math.round(data.location.distance/1000)) + ' km'; } } //location, country, distance $('div.profile__info svg + p[class^="BodyText"]').first().html(name + country + distance); //since, id, known by, visits, online $('section.profile__stats section > p').last().addClass('re-profile-stats mb-').html(`${since}<br>${profileIdInfo}<br>${known}${visits}<br>${lastSince} ${timeTag}`); //authenticity let title = $('.top-info-header p + div > button').attr('title'); $('.top-info-header p + div > button').not('.re-add').addClass('re-add').find('title').text(`${title}${(known1st) ? ` (${(known1st <= 30) ? known1st : '30+'})` : ''}\n${sinceMonthYear}\n${lastSince} ${timeTag}`); //hide visit $('.profile--romeo .top-info-header p[class^="BodyText"]').first().attr('title', 'Profilbesuch verstecken').off().click(function(){ hideVisit(profileId); }); //link to albums $('section.profile__stats section').first().find('div[class^="InfoText-"] p[class^="BaseText"]').click(function(){ changeUrl(`/${profilePath}/${profileName}/gallery`); }).attr('style', 'cursor:pointer').titleLabel('Alle Alben anzeigen'); //complete headline if (data.headline && data.headline.length > 50) { $('div.profile__info p[class^="BodyText"]').last().text(data.headline); } //URLs in headline and profile text $('div.profile__info div.reactView > div > p[class^="BodyText"], section.profile__stats details > div > p[class^="BaseText-sc-"]').each(function() { let replacedText = linkify($(this).html()); $(this).html(replacedText); }); //link travel locations to maps $('section.profile__stats details').has('#travel-list').find('div:not([role="heading"]) > p:first-child').not(':has(.re-add)').each(function() { $(this).wrapInner( `<a target="_blank" href="https://google.com/maps/place/${$(this).text().trim()}" rel="noreferrer noopener" class="re-link-idle re-add" title="Ort in Google Maps anzeigen"></a>` ) }); //move Travel Date and Looking For to top, keeping Albums and B&B at top $('section.profile__stats details').not('.re-add').has('summary :contains("Ich suche"), summary :contains("Looking For"), summary :contains("Recherche")').each(function() { $(this).addClass('re-add').prependTo('section.profile__stats > div > div.reactView:last-child > div'); }); $('section.profile__stats details').has('#travel-list').not('.re-add').addClass('re-add').prependTo('section.profile__stats > div > div.reactView:last-child > div'); $('section.profile__stats section').not('.re-add').has('img + div > p').addClass('re-add').prependTo('section.profile__stats > div > div.reactView:last-child > div'); $('section.profile__stats section').not('.re-add').first().has('a[href*="/gallery"]').addClass('re-add').prependTo('section.profile__stats > div > div.reactView:last-child > div'); } // ***** Handle error page ***** function linksError (jNode) { //... $(jNode).append( `<div style="font-size:0.9em"><br/>...</div>` ); } // ***** Sort groups list by active posts ***** //init let groupsList = []; let viewMode = ''; let counter = 0; let groupsCount = 0; let groupsRefreshed = false; let groupsListloadTime = 0; let lastGroupName = ''; let atoz = false; let linkTextActive = 'Aktive Beiträge', linkTextDefault = 'Standard'; function recentPosts (jNode) { // console.log('recentPosts'); $(jNode).not('.re-groups-def').addClass('re-groups-def').after( `<nav class="re-groups-enh is-hidden"></nav>` ); //insert menu viewMode = localStorage.getItem('REgroupsListView'); let linkText = (viewMode == 'active') ? linkTextActive : linkTextDefault; $('nav.re-groups-def').closest('div[class*="ReactContainer"]').not(':has(span.re-list-head)').prepend(` <div class="mh mt- pv-" style="font-size:.85rem; border-bottom:1px solid rgba(255,255,255,.125)"> <span class="re-list-head">Sortierung</span> <span class="re-list-view ml-" title="Umschalten" role="button" aria-label="Sortierung ändern">${linkText}</span> <span class="re-list-load icon icon-stathistory pl- pr-" title="Aktualisieren"> <span class="re-list-head ml--"></span> </span> </div>` ); //toggle sort mode (recent posts <-> a-z) $('.re-list-head').off().on('dblclick', function() { if (viewMode == 'active') { atoz = !atoz; linkText = linkTextActive = (atoz) ? 'A - Z' : 'Aktive Beiträge'; $('.re-list-view').text(linkText); insertPostsList (groupsList); } }); if (mobile.matches) { $('div.js-header').removeClass('l-hidden-sm'); $('div.Container--xbtQn').hide(); } if (viewMode !== 'active') { $('span.re-list-load').hide(); } //register toggle menu click $('span.re-list-view').click(function() { if (counter == groupsCount) { //not while building groupsList let oldViewMode = localStorage.getItem('REgroupsListView'); if (oldViewMode == 'active') { linkText = linkTextDefault; viewMode = 'default'; $('span.re-list-load').hide(); } else { linkText = linkTextActive; viewMode = 'active'; $('span.re-list-load').show(); } localStorage.setItem('REgroupsListView', viewMode); $('span.re-list-view').text(linkText); handlePostsList(viewMode); } }); //register refresh list click $('span.re-list-load').click(function() { if (counter == groupsCount) { //not while building groupsList groupsList.length = 0; counter = 0; groupsRefreshed = true; groupsListloadTime = new Date().toLocaleTimeString(); $('nav.re-groups-enh').find('a.re-add, button, h4').remove(); $('nav.re-groups-def').hide(); handlePostsList(viewMode); } }); handlePostsList(viewMode); } // ***** Handle posts list ***** function handlePostsList (viewMode) { if (viewMode !== 'active') { $('nav.re-groups-enh').addClass('is-hidden'); $('nav.re-groups-def').show(); let highlighted = 'nav.re-groups-def button'; if ($(highlighted).length) { $(highlighted)[0].scrollIntoView({block: 'center'}); } } else { $('nav.re-groups-def').hide(); $('nav.re-groups-enh').removeClass('is-hidden'); if (groupsList.length > 0) { insertPostsList(groupsList); } else { if (commonGroupsList[0]?.name == location.href.replace(/(.*\/groups\/member\/)([-\w]+)$/, '$2')) { // groupsRefreshed = true; } groupsListloadTime = new Date().toLocaleTimeString('de-DE'); $('nav.re-groups-enh').not(':has(.re-add)').prepend( '<div class="spinner-container re-add"><div class="spinner"></div></div>' ); $.ajax({headers: ajaxHead(), url: '/api/v4/profiles/me/groups?expand=items.*.(membership,activity)&lang=de&length=1000&pick=items.*.(id,name,display_name,membership.is_admin,is_forum_enabled,activity.posts.*,activity.photos.*,preview_pic.url_token),items_total'}) .done(function (data) { groupsList = []; counter = 0; groupsCount = data.items_total; let ajaxUrl = '', name = '', displayName = '', isAdmin = false, picToken = '', actPosts = 0, countPosts = 0, actPhotos = 0, countPhotos = 0; for (let item of data.items) { // loop "posts" for all groups if (item) { name = item.name; displayName = item.display_name; isAdmin = item.membership.is_admin; picToken = (item.preview_pic) ? item.preview_pic.url_token : ''; if (item.activity) { actPosts = (item.activity.posts) ? item.activity.posts.last_accessed : 0; countPosts = (item.activity.posts) ? item.activity.posts.count : 0; actPhotos = (item.activity.photos) ? item.activity.photos.last_accessed : 0; countPhotos = (item.activity.photos) ? item.activity.photos.count : 0; } else { actPosts = 0; countPosts = 0; actPhotos = 0; countPhotos = 0; } if (item.is_forum_enabled) { ajaxUrl = `/api/v4/groups/${item.id}/posts?pick=items.*.(date_created,comments.items.*.(date_created))&expand=items.*.(comments)&lang=de&length=5&sort_criteria=COMMENTED_AT_DESC`; } else { ajaxUrl = `/api/v4/groups/${item.id}/posts?pick=items.*.(date_created)&lang=de&length=5&sort_criteria=COMMENTED_AT_DESC`; } $.ajax({headers: ajaxHead(), url: ajaxUrl, custom: {name: name, displayName: displayName, isAdmin: isAdmin, picToken: picToken, actPosts: actPosts, countPosts: countPosts, actPhotos: actPhotos, countPhotos: countPhotos} }) .done(function (data) { //save name, timestamp, etc. to array (most recent post or comment) let timeList = [], name = '', displayName = '', time = 0, isComment = false, picToken = '', actPosts = 0, countPosts = 0, actPhotos = 0, countPhotos = 0; for (let item of data.items) { if (item.comments?.items[0]) { time = item.comments.items[0].date_created; isComment = true; } else { time = item.date_created; isComment = false; } if (time != 0) time = new Date(time.slice(0,-2) + ':00'); timeList.push({time: time, isComment: isComment}); } //sort by most recent post or comment timeList.sort(function (a,b) { return b.time - a.time; }); if (timeList[0]) time = timeList[0].time; if (timeList[0]) isComment = timeList[0].isComment; name = this.custom.name; displayName = this.custom.displayName.trim(); isAdmin = this.custom.isAdmin; picToken = this.custom.picToken; actPosts = this.custom.actPosts; countPosts = this.custom.countPosts; actPhotos = this.custom.actPhotos; countPhotos = this.custom.countPhotos; if (actPosts != 0) actPosts = new Date(actPosts); if (actPhotos != 0) actPhotos = new Date(actPhotos); // console.log(displayName, timeList); //add to array groupsList.push({time: time, name: name, displayName: displayName, isAdmin: isAdmin, picToken: picToken, isComment: isComment, actPosts: actPosts, countPosts: countPosts, actPhotos: actPhotos, countPhotos: countPhotos, visited: false}); }) .always(function (data) { counter++; if (counter >= groupsCount) { insertPostsList(groupsList); return; } }); } else { counter++; if (counter >= groupsCount) { insertPostsList(groupsList); return; } } } }); } $('span.re-list-load span').text(groupsListloadTime.slice(0,-3)); $('ul.Container--1I9Gx button').click(); } } // ***** Handle groups list after group is loaded ***** function refreshPostsList () { if (groupsRefreshed == false || lastGroupName != location.pathname.replace(/^(\/groups\/member\/)([-\w]+)(.*)/, '$2')) { // if (groupsRefreshed == false) { lastGroupName = location.pathname.replace(/^(\/groups\/member\/)([-\w]+)(.*)/, '$2'); groupsRefreshed = false; } else { groupsRefreshed = true; } if (viewMode == 'active') insertPostsList (groupsList); } // ***** Insert posts list ***** function insertPostsList (groupsList) { //sort by a-z or most recent groupsList.sort(function (a,b) { if (atoz) { return b.isAdmin - a.isAdmin || a.displayName.localeCompare(b.displayName); } else { return b.time - a.time; } }); // console.log(groupsList); //insert list elements on top of MY GROUPS $('nav.re-groups-enh').find('a.re-add, button, div, h4').remove(); $('nav.re-groups-def').hide(); let thumbnail = ''; for (let item of groupsList) { thumbnail = (item.picToken == '') ? '/assets/76d319082f701e66be89.svg' : `/img/usr/squarish/212x212/${item.picToken}.jpg`; $('nav.re-groups-enh').append(` <a href="/groups/member/${item.name}" class="re-add re-groups-listitem"> <div class="re-groups-tile" style="background-image:url(${thumbnail})"></div> <div class="re-groups-entry"> <span class="re-groups-text"> <span> <span lang="" title="${item.displayName}" class="re-groups-name">${item.displayName}<br> <span class="re-groups-time" title="${(item.isComment) ? 'Letzter Kommentar' : 'Letzter Beitrag'} vom ${item.time.toLocaleString('de-DE').slice(0,-3)}">${dateTime(item.time, !touch.matches)}</span> </span> </span> </span> </div> </a>` ); if (item.isComment) { $('nav.re-groups-enh a.re-add').last().append(` <div class="re-groups-new ml-" style="margin-right:.1em" title="Aktueller Kommentar vom ${item.time.toLocaleString('de-DE').slice(0,-3)}"> <svg label="Aktueller Kommentar" role="img" aria-hidden="false" viewBox="0 0 1024 1024"> <path d="M943.3 408.7c-49.9-49.9-118.9-80.7-195-80.7H222.7l.1-183.5L0 367.4l222.8 222.8.1-183.5h525.4c54.4 0 103.6 22.1 139.3 57.7 35.6 35.7 57.6 84.9 57.6 139.3 0 54.4-22 103.6-57.7 139.3-35.7 35.7-84.9 57.7-139.3 57.7H616.3c-14.2 0-25.7 11.5-25.7 25.7v27.5c0 14.2 11.5 25.7 25.7 25.7h131.9c76.2 0 145.1-30.9 195-80.7 49.9-49.9 80.7-118.9 80.7-195 .1-76.3-30.8-145.3-80.6-195.2z"></path> </svg> </div>` ); } if (item.actPosts) { $('nav.re-groups-enh a.re-add').last().append(` <div class="re-groups-new ml-" title="${item.countPosts} ${(item.countPosts == 1) ? 'neuer Beitrag' : 'neue Beiträge'} seit ${item.actPosts.toLocaleString('de-DE').slice(0,-3)}"> <span style="margin-right:.25em">${item.countPosts}</span> <svg label="Neue Beiträge" style="font-size:.675em" role="img" aria-hidden="false" viewBox="0 0 100 100"> <path d="M50 0a50 50 0 100 100A50 50 0 1050 0z"></path> </svg> </div>` ); } if (item.actPhotos) { $('nav.re-groups-enh a.re-add').last().append(` <div class="re-groups-new ml-" title="${item.countPhotos} ${(item.countPhotos == 1) ? 'neues Bild' : 'neue Bilder'} seit ${item.actPhotos.toLocaleString('de-DE').slice(0,-3)}"> <span style="margin-right:.25em">${item.countPhotos}</span> <svg label="Neue Bilder" role="img" aria-hidden="false" viewBox="0 0 1024 1024"> <path d="M656 579c0 80-64 145-144 145s-144-65-144-145 64-145 144-145 144 65 144 145zM512 808c-63 0-120-26-161-68s-67-98-67-162c0-63 26-120 67-162s98-67 161-67 120 25 161 67 67 99 67 162c0 64-26 120-67 162s-98 68-161 68zm449-589H762L644 107c-7-7-16-11-27-11H407c-11 0-20 4-27 11L262 219H63c-35 0-63 28-63 63v583c0 35 28 63 63 63h898c35 0 63-28 63-63V282c0-35-28-63-63-63z"></path> </svg> </div>` ); } if (item.isAdmin) { $('nav.re-groups-enh a.re-add').last().append(` <div class="re-groups-admin ml-" title="Du verwaltest diese Gruppe" aria-label="Du verwaltest diese Gruppe"s> <span>ADMIN</span> </div>` ); } if (item.visited && !groupsRefreshed) { // dim visited groups $('nav.re-groups-enh a.re-add').last().addClass('re-groups-visited'); } } //highlight selected item $('nav.re-groups-enh a.re-add').each(function() { let index = $('nav.re-groups-enh a.re-add').index(this); if ((!mobile.matches && location.href.match(this.href)) || (this.href.match(`/groups/member/${lastGroupName}`) && !groupsRefreshed)) { if (!groupsRefreshed) $(this)[0].scrollIntoView({block: 'center'}); $(this).removeClass('re-groups-visited').addClass('re-groups-selected'); groupsList[index].visited = true; } }); //refresh content on re-click, remove indicators on first click $('nav.re-groups-enh a.re-add').click(function() { groupsRefreshed = false; if (location.href.match(this.href)) { $('ul.Container--ZCCAM button').click(); return false; } }); //insert separators admin/member if needed if (atoz && $('nav.re-groups-enh a.re-add').not(':has(.re-groups-admin)').length) { $('nav.re-groups-enh a.re-add').has('.re-groups-admin').first().before( `<h4 class="gzwUHp ml- mt- mb--">Admin</h4>` ); $('nav.re-groups-enh a.re-add').has('.re-groups-admin').last().after( `<h4 class="gzwUHp ml- mt- mb--">Mitglied</h4>` ); } } // ***** Handle mobile groups navigation (instead of using :has() pseudo class) ***** function handleMobileGroupsNav (jNode) { console.log('mobile groups nav'); // 'div[class*="withNav-"] > div[class*="ReactContainer-"]:not(:has(.re-groups-def)) {flex:0; width:0}' + // 'div[class*="withNav-"] > div[class*="ReactContainer-"]:not(:has(.re-groups-def)) > :is(div, nav) {display:none}' + // 'div[class*="withNav-"] > div[class*="ReactContainer-"]:has(.re-groups-def) + div.js-main {display:none}' + $(jNode).not(':has(.re-groups-def').attr('style', 'flex:0; width:0'); $(jNode).not(':has(.re-groups-def').children('div, nav').hide(); $(jNode).has('.re-groups-def').attr('style', '').next('div.js-main').show(); } // ***** Toggle group manage mode ***** function groupManageMode (jNode) { if (resigned) $(jNode).not(':has(.re-add)').prepend('<span class="re-add">!</span>'); $(jNode).off().on('dblclick', function() { $(this).find('.re-add').remove(); resigned = !resigned; if (resigned) $(this).prepend('<span class="re-add">!</span>'); }); } // ***** Compact view for group posts ***** function groupPostsViewMode (jNode) { let viewMode = localStorage.getItem('REgroupPostsView'); let linkTextCompact = 'Kompakt', linkTextDefault = 'Mit Kommentaren'; let linkText = (viewMode == 'compact') ? linkTextCompact : linkTextDefault; $('div.Container--1cJVr').append( '<span class="re-posts-view" title="Umschalten">' + linkText + '</span>' + '<span class="layout-item icon icon-dropdown dropdown__arrow"></span>' ); $('span.re-posts-view').click(function() { let oldViewMode = localStorage.getItem('REgroupPostsView'); let linkText = linkTextCompact, viewMode = 'compact'; if (oldViewMode == 'compact') { linkText = linkTextDefault; viewMode = 'default'; } localStorage.setItem('REgroupPostsView', viewMode); $('span.re-posts-view').text(linkText); $('span.CommentCount--3uCNR').each(function() { handleGroupComment(this); }); }); } // ***** Show/hide group comments ***** function refreshGroupComments (jNode) { let thisNode = $(jNode).find('span.CommentCount--3uCNR'); // span.CommentCount--1Eef2 handleGroupComment(thisNode); } // ***** Handle a single group post ***** function handleGroupComment (thisNode) { let viewMode = localStorage.getItem('REgroupPostsView'); let timestamp = $(thisNode).parent().parent().nextAll().find('span.PostDate--2LVzF').last().text(); if (viewMode == 'compact') { $(thisNode).parent().parent().nextAll().hide(); if (timestamp == '') { $(thisNode).text('Kommentar schreiben'); } else { $(thisNode).after( '<span class="ml--"> • ' + timestamp + '</span>' ); } $(thisNode).not(':has(a)').wrapInner('<a></a>').off('click').click(function() { $(thisNode).parent().parent().nextAll().toggle(); }); } else { $('div.CommentsArea--3iSoQ, div.js-add-comment').show(); $(thisNode).find('a').contents().unwrap('a'); $(thisNode).off('click'); $(thisNode).next('span').remove(); if (timestamp == '') { $(thisNode).text('0 Kommentare'); } } } // ***** Localize group post date ***** function handleGroupPostDate (jNode) { if ($(jNode).not('.re-done').length) { $(jNode).addClass('re-done'); let date = $(jNode).text().trim(); let localeDate = new Date(date).toLocaleDateString('de-DE'); if (localeDate != 'Invalid Date') $(jNode).text(`${localeDate}`).attr('title', `${date}`); } } // ***** Group posts ***** function handleGroupPosts (jNode) { //... } // ***** Sort group members by distance from travel location, save sorting permanently ***** //init let travelName = ''; if (localStorage.getItem('PR_SETTINGS:groups:members:sorting')?.match(/GROUP_JOIN_DATE_DESC|LAST_LOGIN_DESC|NEARBY_ASC/)) { sessionStorage.setItem('PR_SETTINGS:groups:members:sorting', localStorage.getItem('PR_SETTINGS:groups:members:sorting')); } else { sessionStorage.setItem('PR_SETTINGS:groups:members:sorting', 'LAST_LOGIN_DESC'); } function groupTravelLocation (jNode) { let viewMode = localStorage.getItem('REgroupTravelLocation'); let toggleTravel = 'span.re-member-travel'; $('div.js-members-header div.js-dropdown button').not('.re-done').addClass('re-done').has('div:contains("Entf"), div:contains("In der"), div:contains("Nearby"), div:contains("Cercanos"), div:contains("À prox"), div:contains("Vicini"), div:contains("Por perto")').parent().append( `<span class="re-add re-member-travel icon icon-airplane ml- pl" title="Reiseziel" role="img" aria-label="Reiseziel"><span class="pl-"></span></span>` ); handleTravelLocation(viewMode, toggleTravel); $('span.re-member-travel').off().click(function() { let viewMode = localStorage.getItem('REgroupTravelLocation'); let toggleTravel = 'span.re-member-travel'; let refreshClick = 'ul.Container--ZCCAM button'; viewMode = (viewMode == 'travel') ? 'default' : 'travel'; localStorage.setItem('REgroupTravelLocation', viewMode); handleTravelLocation(viewMode, toggleTravel, refreshClick); }); //save sorting permanently setTimeout(() => { if (sessionStorage.getItem('PR_SETTINGS:groups:members:sorting')?.match(/GROUP_JOIN_DATE_DESC|LAST_LOGIN_DESC|NEARBY_ASC/)) { localStorage.setItem('PR_SETTINGS:groups:members:sorting', sessionStorage.getItem('PR_SETTINGS:groups:members:sorting')); } }, 300); } function handleTravelLocation (viewMode, toggleTravel, refreshClick) { if (viewMode == 'travel') { $(toggleTravel).addClass('re-selected'); if (xhrTravelLat && xhrTravelLong) { $.ajax({headers: ajaxHead(), url: `/api/geocoder/private/name?lat=${xhrTravelLat}&lon=${xhrTravelLong}&lang=de`}) .done(function (data) { if (data[0].name) { travelName = data[0].name; } let travelEdit = '<a href="/explore/edit" class="re-edit-travel icon icon-pen pl-" style="line-height:inherit" title="Reiseziel ändern"></a>'; $(toggleTravel).find('span').html(travelName).attr('title', travelName).addClass('pl-'); $(toggleTravel).next('a.re-edit-travel').remove(); $(toggleTravel).after(travelEdit); travelMode = true; if (refreshClick) $(refreshClick).get(0).click(); }); } else { $.ajax({headers: ajaxHead(), url: `/api/v4/locations/travel`}) .done(function (data) { let travelEdit = ''; if (data.length) { let last = data.length -1; xhrTravelLat = data[last].lat; xhrTravelLong = data[last].long; localStorage.setItem('REtravelLat', xhrTravelLat); localStorage.setItem('REtravelLong', xhrTravelLong); travelName = data[last].name; travelMode = true; travelEdit = '<a href="/explore/edit" class="re-edit-travel icon icon-pen pl-" title="Reiseziel ändern"></a>'; } else { travelMode = false; travelEdit = '<a href="/explore/new" class="re-edit-travel">Klicken, um ein Reiseziel hinzuzufügen!</a>'; } $(toggleTravel).find('span').html(travelName).attr('title', travelName).addClass('pl-'); $(toggleTravel).next('a.re-edit-travel').remove(); $(toggleTravel).after(travelEdit); if (refreshClick) $(refreshClick).get(0).click(); }); } } else { $(toggleTravel).removeClass('re-selected'); $(toggleTravel).find('span').text('').removeAttr('title').removeClass('pl-'); $(toggleTravel).next('a.re-edit-travel').remove(); travelMode = false; if (refreshClick) $(refreshClick).get(0).click(); } } // ***** Show picture info in slide show ***** //init let imgNameOld = ''; function imgInfo (jNode) { //don't handle repeatedly within 500ms let imgName = $('div.swiper-slide-active img').attr('src'); if (imgName === imgNameOld) return; //new picture or after 500ms imgNameOld = imgName; setTimeout(() => { imgNameOld = ''; }, 500); //handle picture let jNodeSlide = $('div.swiper-slide-active img').closest('main'); $(jNodeSlide).find('.re-add').remove(); if (imgName?.match(/^\/img\//)) { let imgNameTxt = uploadDate(`${imgName.substr(imgName.lastIndexOf('/') + 1, 8)}`); info = `<a class="re-add" style="font-size:.8125rem; color:rgba(255,255,255,.5); cursor:default" title="Upload-Datum" href="${imgName}">${imgNameTxt}</a>`; $(jNodeSlide).children('section').children('div').first().children('button').after(info); } //report button $(jNodeSlide).children('section').children('div').first().children('p').attr('style', 'font-size:.9375rem'); //URLs in picture caption setTimeout(() => { $('#metadata-bar div > div > p[class^="ResponsiveBodyText"]').first().each(function() { let replacedText = linkify($(this).text()); $(this).html(replacedText); }); }, 0); //localize picture date setTimeout(() => { let imgDate = $('#metadata-bar > div > div > p').last().text().trim(); if (imgDate.match(/\d+\w{2} \w+ \d{4}/)) { let localeDate = new Date(imgDate.replace(/(^|: )(\d+)(\w{2}) (\w+ \d{4})/, '$2 $4')).toLocaleDateString(); if (localeDate != 'Invalid Date') $('#metadata-bar > div > div > p').last().text(localeDate).attr('title', `${imgDate}`); } }, 0); } // ***** Remove refresh for slide show likes list ***** function handleSlideshowLikes (jNode) { $(jNode).closest('div').children('button + div, button').remove(); } // ***** Show picture info in picture rating ***** function ratingInfo (jNode) { $('#picture-rating .re-add').remove(); $('#picture-rating button').blur(); let imgName = $('#picture-rating img').attr('src'); if (imgName) { let imgNameTxt = `${imgName.substr(imgName.lastIndexOf('/') + 1, 5)}...`; let imgDate = uploadDate(`${imgName.substr(imgName.lastIndexOf('/') + 1, 8)}`); let imgNameMax = sessionStorage.getItem('REratingMax'); imgNameMax = (imgNameMax ? imgNameMax : imgNameTxt); if (imgNameTxt >= imgNameMax) { sessionStorage.setItem('REratingMax', imgNameTxt); } let color = (parseInt(imgNameTxt,16) + 1 < parseInt(imgNameMax,16)) ? 'rgba(255,0,0,.8)' : 'rgba(255,255,255,.375)'; $('#picture-rating button').has('p').after( `<a class="re-rating-date re-add" style="color:${color}" title="Upload-Datum" href="${imgName}">${imgDate}</a>` ); } //set focus on reload button if (!touch.matches) { $('#picture-rating button[class^="SecondaryButton__Element-"]').focus(); } } // ***** Relogin after timeout ***** function reLogin (jNode) { if ($(jNode).not('.re-add').addClass('re-add').children('span').filter(':contains("Erneut einloggen"), :contains("Log in again"), :contains("Reconnexion")').length) { $(jNode).closest('section').parent('div').addClass('re-relogin-frame'); $(jNode).closest('section').find('div > button').hide(); $(jNode).closest('section').find('h1').text(''); $(jNode).closest('section').find('div > img').replaceWith('<div class="spinner-container"><div class="spinner"></div></div>'); $(jNode).closest('section').children('p').text('Erneut einloggen ...'); setTimeout(() => { // if (location.pathname == '/visitors' || location.pathname.match(/\/messenger\/contacts/)) { // location.replace('/'); // fix for broken profiles after reload when VISITORS or CONTACTS is selected // } else { location.reload(); // } }, 600); } else { $(jNode).closest('div[class^="Modal__StyledModal"]').find('section p').off().on('dblclick', function() { $(this).closest('div[class^="Modal__StyledModal"]').remove(); $('body').attr('class', ''); }); } } // ***** XHR ***** //test localStorage.setItem('REpostFromDeleted', `${(GM_info?.script?.name.match(/-DEV|-BETA/)) ? true : false}`); localStorage.setItem('REtestMode', `${(GM_info?.script?.name.match(/-DEV|-BETA/)) ? true : false}`); //init let xhrTravelLat = localStorage.getItem('REtravelLat'); let xhrTravelLong = localStorage.getItem('REtravelLong'); let travelMode = (localStorage.getItem('REradarTravelLocation') === 'travel'); let resigned = false; let xhrFull = ''; let eyecandyActive = (localStorage.getItem('REeyecandyActive') === 'true'); let filterNoEntry = (localStorage.getItem('REfilterNoEntry') === 'true'); let postFromDeleted = (localStorage.getItem('REpostFromDeleted') === 'true'); let testMode = (localStorage.getItem('REtestMode') === 'true'); (function() { let oldXHROpen = window.XMLHttpRequest.prototype.open; window.XMLHttpRequest.prototype.open = function(method, url, async, user, password) { if (url.match(/v4\/messages\//)) { //... } if (url.match(/v4\/messages\/conversations\?/)) { //url = url.replace('&length=15', '&length=120'); } if (url.match(/v4\/contacts\?/)) { if ($('#contacts-custom-tags a.ui-tag--selected span.ui-tag__label').text().trim() == '[ A-Z ]') { url += '&sort_criteria=NAME_ASC'; url = url.replace(/&filter%5Btags%5D%5B%5D\=\d+/, ``); } if ($('#contacts-custom-tags a.ui-tag--selected span.ui-tag__label').text().trim() == '[ Login ]') { url += '&sort_criteria=LAST_LOGIN_DESC'; url = url.replace(/&filter%5Btags%5D%5B%5D\=\d+/, ``); } if ($('#contacts-custom-tags a.ui-tag--selected span.ui-tag__label').text().trim() == '[ Online ]') { url += '&filter[online]=true'; url = url.replace(/&filter%5Btags%5D%5B%5D\=\d+/, ``); } //url += '&sort_criteria=LAST_LOGIN_DESC'; //url += '&sort_criteria=NAME_ASC'; //url += '&filter[online]=true'; url = url.replace('/contacts?length=100&pick=items.*.profile&lang=de', '/contacts?length=999&pick=items.*.profile&lang=de'); } if (location.pathname.match(/^\/messenger\/contacts\/name/)) { if (url.match(/filter%5Busername%5D\=/)) { url += '&sort_criteria=NAME_ASC'; url = url.replace(/filter%5Busername%5D\=\*/, ''); } } if (travelMode) { if (location.pathname.match(/^\/radar\//)) { url = url.replace(/filter%5Blocation%5D%5Blat%5D\=[-0-9\.]+/, `filter[location][lat]=${xhrTravelLat}`); url = url.replace(/filter%5Blocation%5D%5Blong%5D\=[-0-9\.]+/, `filter[location][long]=${xhrTravelLong}`); } //url = url.replace(/filter%5Btravellers_filter%5D\=EXCLUDED/, ''); //url = url.replace(/filter%5Btravellers_filter%5D\=INCLUDED/, 'filter%5Btravellers_filter%5D=EXCLUDED'); //url = url.replace(/sort_criteria\=NEARBY_ASC/, 'sort_criteria=NEARBY_DESC'); } if (location.pathname.match(/^\/(radar|hunqz)\//) && url.match(/filter%5Blocation%5D/)) { let radius = $('.js-distance-radius .noUi-handle').attr('aria-valuenow'); if (radius >= 94500 && radius < 95500) { //95 url = url.replace(/filter%5Blocation%5D%5Bradius%5D\=[0-9\.]+/, `filter[location][radius]=${250000}`); } if (radius >= 95500 && radius < 96500) { //96 url = url.replace(/filter%5Blocation%5D%5Bradius%5D\=[0-9\.]+/, `filter[location][radius]=${500000}`); } if (radius >= 96500 && radius < 97500) { //97 url = url.replace(/filter%5Blocation%5D%5Bradius%5D\=[0-9\.]+/, `filter[location][radius]=${1000000}`); } if (radius >= 97500 && radius < 98500) { //98 url = url.replace(/filter%5Blocation%5D%5Bradius%5D\=[0-9\.]+/, `filter[location][radius]=${2000000}`); } if (radius >= 98500 && radius < 99500) { //99 url = url.replace(/filter%5Blocation%5D%5Bradius%5D\=[0-9\.]+/, `filter[location][radius]=${4000000}`); } } if (url.match(/v4\/groups\//)) { if (travelMode) { url = url.replace(/filter%5Blocation%5D%5Blat%5D\=[-0-9\.]+/, `filter[location][lat]=${xhrTravelLat}`); url = url.replace(/filter%5Blocation%5D%5Blong%5D\=[-0-9\.]+/, `filter[location][long]=${xhrTravelLong}`); } if (resigned) { url = url.replace('statuses[]=REJECTED', 'statuses[]=NONE'); } } if (url.match(/v4\/profiles\/popular/)) { if (travelMode && !url.match(/&scrollable=false/)) { url = url.replace('sort_criteria=LAST_LOGIN_DESC', 'sort_criteria=NEARBY_ASC'); url = url.replace(/filter%5Blocation%5D%5Blat%5D\=[-0-9\.]+/, `filter[location][lat]=${xhrTravelLat}`); url = url.replace(/filter%5Blocation%5D%5Blong%5D\=[-0-9\.]+/, `filter[location][long]=${xhrTravelLong}`); } else if (!eyecandyActive && url.match(/&scrollable=false/)) { url = url.replace('sort_criteria=NEARBY_ASC', 'sort_criteria=LAST_LOGIN_DESC'); } //url = url.replace('sort_criteria=LAST_LOGIN_DESC', 'sort_criteria=SIGNUP_DESC'); } if (location.pathname.match(/^\/explore\//) && url.match(/v4\/profiles\?lang/)) { let loc = location.pathname.match(/[-0-9\.]+/g); xhrTravelLat = loc[0]; xhrTravelLong = loc[1]; localStorage.setItem('REtravelLat', xhrTravelLat); localStorage.setItem('REtravelLong', xhrTravelLong); //let radius = $('.js-distance-radius .noUi-handle').attr('aria-valuenow'); //url = url.replace('sort_criteria=NEARBY_ASC', `sort_criteria=LAST_LOGIN_DESC&filter[location][radius]=${radius}`); //url = url.replace('sort_criteria=NEARBY_ASC', `sort_criteria=SIGNUP_DESC&filter[location][radius]=${radius}`); } //include "no entry" to filter if (filterNoEntry) { if (url.match(/\/profiles\?/)) { const categories = [ '&filter%5Bpersonal%5D%5Bgender_orientation%5D%5Bgender%5D%5B%5D=', '&filter%5Bpersonal%5D%5Bgender_orientation%5D%5Borientation%5D%5B%5D=', '&filter%5Bpersonal%5D%5Blooking_for%5D%5B%5D=', '&filter%5Bpersonal%5D%5Bbody_type%5D%5B%5D=', '&filter%5Bpersonal%5D%5Bbody_hair%5D%5B%5D=', '&filter%5Bpersonal%5D%5Bhair_color%5D%5B%5D=', '&filter%5Bpersonal%5D%5Bhair_length%5D%5B%5D=', '&filter%5Bpersonal%5D%5Bethnicity%5D%5B%5D=', '&filter%5Bsexual%5D%5Banal_position%5D%5B%5D=', '&filter%5Bsexual%5D%5Bdick_size%5D%5B%5D=', '&filter%5Bsexual%5D%5Bconcision%5D%5B%5D=', '&filter%5Bsexual%5D%5Bsafer_sex%5D%5B%5D=', '&filter%5Bsexual%5D%5Bfetish%5D%5B%5D=', '&filter%5Bsexual%5D%5Bsm%5D%5B%5D=', '&filter%5Bsexual%5D%5Bfisting%5D%5B%5D=' ] for (let item of categories) { url = url.replace(item, item + 'NO_ENTRY' + item) } } } //full profile if (url.match(/v4\/(hunqz\/)?profiles\/[-\w]+\/full\?/)) { this.addEventListener('load', function() { xhrFull = JSON.parse(this.response) // console.log('xhrFull'); }); } //show group posts of deleted users if (postFromDeleted) { if (url.match(/v4\/groups\/\d+\/posts\?/)) { this.addEventListener('load', function() { try { this.xhr = JSON.parse(this.response) for (let item of this.xhr.items) { if (item.deleted) { // console.log(`deleted`); delete item.deleted; //item.edit_status = 'NO_EDIT'; item.content = `[Gelöschter Beitrag]\n${item.content}`; } if (item.owner.deletion_date) { // console.log(`deletion_date`); delete item.owner.deletion_date; item.content = `[Profil gelöscht]\n\n${item.content}`; } } Object.defineProperty(this, 'responseText', { writable: true }); this.responseText = JSON.stringify(this.xhr) } catch(e) { } }); } } return oldXHROpen.apply(this, arguments); } })(); // ***** Run at login ***** //init let commonGroupsList = [], commonGroupsLoaded = false, visitorsList = [], visitsList = [], visitorsLoaded = false, visitsLoaded = false; function runAtLogin (jNode) { //init common groups groupsRefreshed = true; commonGroupsList = []; $.ajax({headers: ajaxHead(), url: '/api/v4/profiles/me/groups?lang=de&length=10000&pick=items.*.(id,name,display_name)'}) .done(function (data) { for (let item of data.items) { commonGroupsList.push(item); } commonGroupsLoaded = true; if (testMode) console.log(commonGroupsList); //get initial group name const nameIndex = (item) => item.name == lastGroupName; if (commonGroupsList.findIndex(nameIndex) == -1) { if (commonGroupsList.length > 0) { lastGroupName = commonGroupsList[0].name; } else { lastGroupName = ''; } } }); //visitors, visits $.ajax({headers: ajaxHead(), url: '/api/v4/visitors?lang=de&length=10000&pick=items_limited,items.*.(name,date_visited)'}) .done(function (data) { for (let item of data.items) { if (data.items_limited == undefined || visitorsList.length < data.items_limited) { visitorsList.push(item); } } visitorsLoaded = true; if (testMode) console.log(visitorsList, data.items_limited); }); $.ajax({headers: ajaxHead(), url: '/api/v4/visits?lang=de&length=10000&pick=items_limited,items.*.(name,date_visited)'}) .done(function (data) { for (let item of data.items) { if (data.items_limited == undefined || visitsList.length < data.items_limited) { visitsList.push(item); } } visitsLoaded = true; if (testMode) console.log(visitsList, data.items_limited); }); } // ***** MutationObserver ***** /*** Functions for accessibility tweaks ***/ function makeHeading(el, level) { el.setAttribute("role", "heading"); el.setAttribute("aria-level", level); } function makeRegion(el, label) { el.setAttribute("role", "main"); el.setAttribute("aria-label", label); } function makeButton(el, label) { el.setAttribute("role", "button"); if (label) el.setAttribute("aria-label", label); } function makeButtonFromText(el, label) { el.setAttribute("role", "button"); if (!label) label = ''; el.setAttribute("aria-label", `${label}${el.textContent.trim()}`); } function makeIcon(el, label) { el.setAttribute("role", "img"); el.setAttribute("aria-label", label); } function makePresentational(el) { el.setAttribute("role", "presentation"); } function setLabel(el, label) { el.setAttribute("aria-label", label); } function setLabelFromTitle(el, label) { if (!label) label = ''; el.setAttribute("aria-label", `${label}${el.getAttribute('title')}`); } function setLabelFromText(el) { el.setAttribute("aria-label", el.textContent.trim()); } function setLabelFromChildText(el) { el.parentNode.setAttribute("aria-label", el.textContent.trim()); } function makeRadio(el) { el.setAttribute("role", "radio"); el.setAttribute("aria-checked", "false"); } function makeRadioChecked(el) { el.setAttribute("role", "radio"); el.setAttribute("aria-checked", "true"); } /*** Code to apply the tweaks when appropriate ***/ function applyTweaks(root, tweaks) { for (let tweak of tweaks) { for (let el of root.querySelectorAll(tweak.selector)) { if (Array.isArray(tweak.tweak)) { let [func, ...args] = tweak.tweak; func(el, ...args); } else { tweak.tweak(el); } } } } function initMutationObserver() { applyTweaks(document, LOAD_TWEAKS); applyTweaks(document, DYNAMIC_ELEMENT_ADDED_TWEAKS); } let observer = new MutationObserver(function(mutations) { for (let mutation of mutations) { try { if (mutation.type === "childList") { for (let node of mutation.addedNodes) { if (node.nodeType != Node.ELEMENT_NODE) { continue; } applyTweaks(node, DYNAMIC_ELEMENT_ADDED_TWEAKS); // console.log('MO element node added'); } /*for (let node of mutation.removedNodes) { if (node.nodeType != Node.ELEMENT_NODE) { continue; } applyTweaks(node, DYNAMIC_TWEAKS); }*/ /* } else if (mutation.type === "attributes") { if (mutation.attributeName == "class") { applyTweaks(mutation.target, DYNAMIC_ATTR_ONLY_TWEAKS); } */ } } catch (e) { // Catch exceptions for individual mutations so other mutations are still handled console.log(`Exception while handling mutation: ${e}`); } } }); observer.observe(document, {childList: true, subtree: true}); let observerAttr = new MutationObserver(function(mutations) { for (let mutation of mutations) { try { if (mutation.type === "attributes") { if (mutation.attributeName == "class") { applyTweaks(mutation.target, DYNAMIC_ATTR_ONLY_TWEAKS); // console.log('MO attr only'); } } if (mutation.type === "childList") { applyTweaks(mutation.target, DYNAMIC_ANY_NODE_TWEAKS); // console.log('MO any node'); } } catch (e) { // Catch exceptions for individual mutations so other mutations are still handled console.log(`Exception while handling mutation: ${e}`); } } }); observerAttr.observe(document, {childList: true, subtree: true, attributes: true, attributeFilter: ["class"]}); /*** Define the actual tweaks ***/ // Tweaks to be applied on load const LOAD_TWEAKS = [ ] // Tweaks to be applied whenever an element node is added const DYNAMIC_ELEMENT_ADDED_TWEAKS = [ //RomeoEnhancer (see also waitForKeyElements below) {selector: '#search input', tweak: searchInput}, {selector: ':is(.layer-left-navigation, header) li', tweak: handleMainMenu}, {selector: 'section.js-main-stage ul[class^="Tabbed-nav-"] li.is-selected', tweak: handleTabMenu}, {selector: 'div.js-filter-button button', tweak: handleBookmark}, {selector: '#messenger div:is(.js-correspondence, .js-header) div.reactView div > a > p', tweak: showLoginLocation}, {selector: '.js-profile-footprints h1', tweak: handleFootprints}, {selector: '.js-quick-filter .js-anal-position > div', tweak: handleFilterNoEntry}, {selector: '#messenger div.js-chat .reactView a[href^="/messenger/chat"]', tweak: handleMessage}, {selector: '#messages-list p a', tweak: handleMessageLink}, {selector: '#messenger div.js-contacts .reactView a[href^="/messenger/contacts"]', tweak: handleContacts}, {selector: '#contacts-custom-tags .js-remove', tweak: handleTagRemove}, {selector: ':is(div.js-wrapper, div.js-admins, #group-preview) a.js-contact', tweak: handleContactStrip}, {selector: 'a[href^="/group/"] div[class*="Tile__BaseTile-"]:not(.re-done)', tweak: handleGroupTiles}, {selector: '.js-wrapper a[href^="/eyecandy"] h2', tweak: handleDiscoverEyecandy}, {selector: ':is(a div.BIG, a div.SMALL, button div.LIST) div > span[class^="sc-"]', tweak: handleTiles}, {selector: 'div.stream__content a.listitem__body .js-username p, div.stream__content div.js-list', tweak: handleStream}, {selector: 'section.profile__stats section > p[class^="BaseText"], section.profile__stats ol', tweak: handleProfile}, {selector: 'div[class*="SidebarContentContainer-"] div[class*="Main-"] > div', tweak: refreshPostsList}, {selector: '#manage div[class^="FilterBar__Container"] > div > div', tweak: groupManageMode}, {selector: 'div.js-members-header div.js-dropdown button', tweak: groupTravelLocation}, {selector: '#liked-by-grid', tweak: handleSlideshowLikes}, {selector: '#picture-rating img, #picture-rating p[class^="Text-sc-"]', tweak: ratingInfo}, {selector: 'section[class^="PopupWindow__Content"] button[class^="PrimaryButton__Element"]', tweak: reLogin}, //accessibility: navigation items with badges {selector: '.icon-search', tweak: [makeIcon, "Suchen"]}, {selector: '.icon-visitor', tweak: [makeIcon, "Besucher"]}, {selector: '.icon-chat', tweak: [makeIcon, "Messages"]}, {selector: '.icon-notification-bell', tweak: [makeIcon, "Activity Stream"]}, {selector: '.ui-status--online', tweak: [makeIcon, "Online"]}, {selector: '.ui-status--date', tweak: [makeIcon, "Date"]}, {selector: '.ui-status--sex', tweak: [makeIcon, "Now"]}, {selector: '.icon-airplane', tweak: [makeIcon, "Travel"]}, {selector: '.icon-save-contact', tweak: [makeIcon, "Kontakte"]}, {selector: '.js-nav-item .icon-group-members', tweak: [makeIcon, "Meine Gruppen"]}, //accessibility: profile screen {selector: '.profile--romeo', tweak: [makeRegion, "Romeo-Profil"]}, {selector: '.profile--hunqz', tweak: [makeRegion, "Hunqz-Profil"]}, {selector: '.icon-add-footprint', tweak: [makeButton, "Fußtaps vergeben"]}, {selector: '.js-remove-footprint', tweak: [setLabelFromTitle]}, {selector: '.js-quickshare-trigger', tweak: [setLabel, "QuickShare-Album teilen"]}, {selector: '.icon-default-contact', tweak: [makeIcon, "Nutzer speichern"]}, {selector: '[id^="profile-"] .icon-save-contact', tweak: [makeIcon, "Nutzer speichern"]}, {selector: '#visits > div', tweak: [makeRegion, "Besucher"]}, {selector: '.icon-back', tweak: [makeIcon, "Zurück"]}, {selector: '.icon-next', tweak: [makeIcon, "Weiter"]}, {selector: '.icon-open-menu-ver', tweak: [makeIcon, "Menü öffnen"]}, {selector: '.icon-open-stats', tweak: [makeIcon, "Profildetails"]}, {selector: '.js-attach-pictures', tweak: [setLabel, "Bilder anhängen"]}, {selector: '.js-submit', tweak: [setLabel, "Abschicken"]}, {selector: 'button[class^="Close--"], button.js-close-button, .js-close-icon button', tweak: [setLabel, "Schließen"]}, {selector: '.js-close-spotlight', tweak: [makeButton, "Schließen"]}, {selector: '.js-hide.js-plus', tweak: [setLabel, "Profilbesuch verstecken"]}, {selector: '.profile-section .reactView p[class^="BodyText"]', tweak: [makeHeading, "3"]}, {selector: '.top-info-header p[class^="BodyText"]', tweak: [makeHeading, "1"]}, {selector: 'button[class^="CollapsibleSection"] > p', tweak: [setLabelFromChildText]}, //accessibility: other {selector: '.messages-send__select-button.messages-button-react-view', tweak: [setLabel, "Templates, Standort, Bilder senden"]}, {selector: ':not(.js-nav-item) > .icon-group-members', tweak: [makeIcon, "Gruppe"]}, {selector: '.js-settings-privacy div[class*="Radio-"]', tweak: [makeRadio]}, {selector: '.js-settings-privacy div[class*="Selected-"] div[class*="Radio-"]', tweak: [makeRadioChecked]}, ] // Tweaks to be applied on any node changes const DYNAMIC_ANY_NODE_TWEAKS = [ //RomeoEnhancer {selector: '#offcanvas-nav main div > p[class^="MiniText"]:not(.re-done)', tweak: handleVersion}, {selector: '.js-chat div[class^="Box"] + div > p[class^="SpecialText"]:not(.re-done)', tweak: previewMessage}, {selector: '#messages-list p[class^="SpecialText"]:not(.re-done)', tweak: handleMessageScroll}, {selector: 'div.js-correspondence div.js-header-region div[class*="ContextMenu__"] ul', tweak: threadOptionsMenu}, {selector: ':is(nav.cYfjZv, nav.jvgYMy, nav.WGgGs, nav.fXsTKd):not(.re-groups-def)', tweak: recentPosts}, {selector: ':is(.js-post-list, .js-post) .js-date span', tweak: handleGroupPostDate}, // {selector: 'div[class*="withNav-"] > div[class*="ReactContainer-"]', tweak: handleMobileGroupsNav}, ] // Tweaks to be applied on attribute changes const DYNAMIC_ATTR_ONLY_TWEAKS = [ //RomeoEnhancer {selector: 'div.swiper-slide.swiper-slide-active div.swiper-zoom-container, #metadata-bar p', tweak: imgInfo}, ] initMutationObserver(); // ***** waitForKeyElements (for nodes not handled by MutationObserver) ***** waitForKeyElements ('div#marionette.is-logged-in', runAtLogin, true); waitForKeyElements ('div.js-chat .js-scrollable div[class="js-paging-spinner spinner-container l-fancy"]', fixScroll, true);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址