diff --git a/public/css/mobile-styles.css b/public/css/mobile-styles.css
index c5e4eb1a7..68534d8a2 100644
--- a/public/css/mobile-styles.css
+++ b/public/css/mobile-styles.css
@@ -28,15 +28,22 @@
z-index: 30;
overflow: hidden;
right: 0;
- top: 50px;
- aspect-ratio: 2 / 3;
width: fit-content;
max-height: calc(60vh - 60px);
max-height: calc(60svh - 60px);
max-width: 90vw;
max-width: 90svw;
left: 50%;
- transform: translateX(-50%);
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%);
+ align-items: center;
+ justify-content: center;
+ height: fit-content;
+ width: 100%;
+ }
+
+ .zoomed_avatar .dragClose {
+ display: unset;
}
/* .world_entry_thin_controls, */
@@ -347,15 +354,18 @@
}
body:not(.waifuMode) .zoomed_avatar {
-
- width: fit-content;
max-height: calc(60vh - 60px);
max-height: calc(60svh - 60px);
max-width: 90vw;
max-width: 90svw;
+ left: 50%;
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%);
+ align-items: center;
+ justify-content: center;
+ height: fit-content;
+ width: 100%;
}
-
-
}
/*portrait mode phones*/
@@ -373,10 +383,13 @@
overflow: hidden;
display: none;
right: 0;
- top: 50px;
- aspect-ratio: 2 / 3;
left: 50%;
- transform: translateX(-50%);
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%);
+ align-items: center;
+ justify-content: center;
+ height: fit-content;
+ width: 100%;
}
.drawer25pWidth {
diff --git a/public/css/toggle-dependent.css b/public/css/toggle-dependent.css
index 3f90edc42..30fb33bcf 100644
--- a/public/css/toggle-dependent.css
+++ b/public/css/toggle-dependent.css
@@ -393,6 +393,7 @@ body.waifuMode .zoomed_avatar {
margin: 0 auto;
top: 50px;
aspect-ratio: 2 / 3;
+ height: auto;
}
/* movingUI*/
diff --git a/public/index.html b/public/index.html
index a14973c20..2b9a2e82b 100644
--- a/public/index.html
+++ b/public/index.html
@@ -49,6 +49,7 @@
+
@@ -3749,6 +3750,11 @@
Tags as Folders
+
Miscellaneous
@@ -5952,8 +5958,16 @@
-
-
![]()
+
+
+
![]()
+
diff --git a/public/lib/jquery.izoomify.js b/public/lib/jquery.izoomify.js
new file mode 100644
index 000000000..f8a9e1e91
--- /dev/null
+++ b/public/lib/jquery.izoomify.js
@@ -0,0 +1,216 @@
+/*!
+* @name: jquery-izoomify
+* @version: 1.0
+* @author: Carl Lomer Abia
+*/
+
+(function ($) {
+ var defaults = {
+ callback: false,
+ target: false,
+ duration: 120,
+ magnify: 1.2,
+ touch: true,
+ url: false
+ };
+
+ var _izoomify = function (target, duration, magnify, url) {
+ var xPos,
+ yPos,
+ $elTarget = $(target),
+ $imgTarget = $elTarget.find('img:first'),
+ imgOrigSrc = $imgTarget.attr('src'),
+ imgSwapSrc,
+ defaultOrigin = 'center top ' + 0 + 'px',
+ resultOrigin,
+ dUrl = 'data-izoomify-url',
+ dMagnify = 'data-izoomify-magnify',
+ dDuration = 'data-izoomify-duration',
+ eClass = 'izoomify-in',
+ eMagnify,
+ eDuration;
+
+ function imageSource(imgSource) {
+ var _img = new Image();
+ _img.src = imgSource;
+ return _img.src;
+ }
+
+ function getImageAttribute($img, dataAttribute, defaultAttribute) {
+ if ($img.attr(dataAttribute)) {
+ return $img.attr(dataAttribute);
+ }
+
+ return defaultAttribute;
+ }
+
+ function getImageSource($img, dataImageSource, defaultImageSource) {
+ if ($img.attr(dataImageSource)) {
+ return imageSource($img.attr(dataImageSource));
+ }
+
+ return defaultImageSource ? imageSource(defaultImageSource) : false;
+ }
+
+ function getTouches(e) {
+ return e.touches || e.originalEvent.touches;
+ }
+
+ imgSwapSrc = getImageSource($imgTarget, dUrl, url);
+
+ eMagnify = getImageAttribute($imgTarget, dMagnify, magnify);
+
+ eDuration = getImageAttribute($imgTarget, dDuration, duration);
+
+ $elTarget
+ .addClass(eClass)
+ .css({
+ 'position': 'relative',
+ 'overflow': 'hidden'
+ });
+
+ $imgTarget.css({
+ '-webkit-transition-property': '-webkit-transform',
+ 'transition-property': '-webkit-transform',
+ '-o-transition-property': 'transform',
+ 'transition-property': 'transform',
+ 'transition-property': 'transform, -webkit-transform',
+ '-webkit-transition-timing-function': 'ease',
+ '-o-transition-timing-function': 'ease',
+ 'transition-timing-function': 'ease',
+ '-webkit-transition-duration': eDuration + 'ms',
+ '-o-transition-duration': eDuration + 'ms',
+ 'transition-duration': eDuration + 'ms',
+ '-webkit-transform': 'scale(1)',
+ '-ms-transform': 'scale(1)',
+ 'transform': 'scale(1)',
+ '-webkit-transform-origin': defaultOrigin,
+ '-ms-transform-origin': defaultOrigin,
+ 'transform-origin': defaultOrigin
+ });
+
+ return {
+ moveStart: function (e, hasTouch) {
+ var o = $(target).offset();
+
+ if (hasTouch) {
+ e.preventDefault();
+ xPos = getTouches(e)[0].clientX - o.left;
+ yPos = getTouches(e)[0].clientY - o.top;
+ } else {
+ xPos = e.pageX - o.left;
+ yPos = e.pageY - o.top;
+ }
+
+ resultOrigin = xPos + 'px ' + yPos + 'px ' + 0 + 'px';
+
+ $imgTarget
+ .css({
+ '-webkit-transform': 'scale(' + eMagnify + ')',
+ '-ms-transform': 'scale(' + eMagnify + ')',
+ 'transform': 'scale(' + eMagnify + ')',
+ '-webkit-transform-origin': resultOrigin,
+ '-ms-transform-origin': resultOrigin,
+ 'transform-origin': resultOrigin
+ })
+ .attr('src', imgSwapSrc || imgOrigSrc);
+ },
+ moveEnd: function () {
+ this.reset();
+ },
+ reset: function () {
+ resultOrigin = defaultOrigin;
+
+ $imgTarget
+ .css({
+ '-webkit-transform': 'scale(1)',
+ '-ms-transform': 'scale(1)',
+ 'transform': 'scale(1)',
+ '-webkit-transform-origin': resultOrigin,
+ '-ms-transform-origin': resultOrigin,
+ 'transform-origin': resultOrigin
+ })
+ .attr('src', imgOrigSrc);
+ }
+ }
+ };
+
+ $.fn.izoomify = function (options) {
+ return this.each(function () {
+ var settings = $.extend({}, defaults, options || {}),
+ $target = settings.target && $(settings.target)[0] || this,
+ src = this,
+ $src = $(src),
+ mouseStartEvents = 'mouseover.izoomify mousemove.izoomify',
+ mouseEndEvents = 'mouseleave.izoomify mouseout.izoomify',
+ touchStartEvents = 'touchstart.izoomify touchmove.izoomify',
+ touchEndEvents = 'touchend.izoomify';
+
+ var izoomify = _izoomify($target, settings.duration, settings.magnify, settings.url);
+
+ function startEvent(e, hasTouch) {
+ izoomify.moveStart(e, hasTouch);
+ }
+
+ function endEvent($src) {
+ izoomify.moveEnd();
+
+ if ($src) {
+ $src
+ .off(touchStartEvents)
+ .off(touchEndEvents);
+ }
+ }
+
+ function resetImage() {
+ izoomify.reset();
+ }
+
+ $src.one('izoomify.destroy', function () {
+
+ $src.removeClass('izoomify-in');
+
+ resetImage();
+
+ $src
+ .off(mouseStartEvents)
+ .off(mouseEndEvents);
+
+ if (settings.touch) {
+ $src
+ .off(touchStartEvents)
+ .off(touchStartEvents);
+ }
+
+ $target.style.position = '';
+ $target.style.overflow = '';
+
+ }.bind(this));
+
+ $src
+ .on(mouseStartEvents, function (e) {
+ startEvent(e);
+ })
+ .on(mouseEndEvents, function () {
+ endEvent();
+ });
+
+ if (settings.touch) {
+ $src
+ .on(touchStartEvents, function (e) {
+ e.preventDefault();
+ startEvent(e, true);
+ })
+ .on(touchEndEvents, function () {
+ endEvent();
+ });
+ }
+
+ if ($.isFunction(settings.callback)) {
+ settings.callback.call($src);
+ }
+ });
+ };
+
+ $.fn.izoomify.defaults = defaults;
+}(window.jQuery));
\ No newline at end of file
diff --git a/public/script.js b/public/script.js
index b4ef72729..b96cd8064 100644
--- a/public/script.js
+++ b/public/script.js
@@ -10227,7 +10227,9 @@ jQuery(async function () {
const avatarSrc = isDataURL(thumbURL) ? thumbURL : charsPath + targetAvatarImg;
if ($(`.zoomed_avatar[forChar="${charname}"]`).length) {
console.debug('removing container as it already existed');
- $(`.zoomed_avatar[forChar="${charname}"]`).remove();
+ $(`.zoomed_avatar[forChar="${charname}"]`).fadeOut(animation_duration, () => {
+ $(`.zoomed_avatar[forChar="${charname}"]`).remove();
+ });
} else {
console.debug('making new container from template');
const template = $('#zoomed_avatar_template').html();
@@ -10238,18 +10240,43 @@ jQuery(async function () {
newElement.find('.drag-grabber').attr('id', `zoomFor_${charname}header`);
$('body').append(newElement);
- if (messageElement.attr('is_user') == 'true') { //handle user avatars
- $(`.zoomed_avatar[forChar="${charname}"] img`).attr('src', thumbURL);
- } else if (messageElement.attr('is_system') == 'true' && !isValidCharacter) { //handle system avatars
- $(`.zoomed_avatar[forChar="${charname}"] img`).attr('src', thumbURL);
+ newElement.fadeIn(animation_duration);
+ const zoomedAvatarImgElement = $(`.zoomed_avatar[forChar="${charname}"] img`);
+ if (messageElement.attr('is_user') == 'true' || (messageElement.attr('is_system') == 'true' && !isValidCharacter)) { //handle user and system avatars
+ zoomedAvatarImgElement.attr('src', thumbURL);
+ zoomedAvatarImgElement.attr('data-izoomify-url', thumbURL);
} else if (messageElement.attr('is_user') == 'false') { //handle char avatars
- $(`.zoomed_avatar[forChar="${charname}"] img`).attr('src', avatarSrc);
+ zoomedAvatarImgElement.attr('src', avatarSrc);
+ zoomedAvatarImgElement.attr('data-izoomify-url', avatarSrc);
}
loadMovingUIState();
- $(`.zoomed_avatar[forChar="${charname}"]`).css('display', 'block');
+ $(`.zoomed_avatar[forChar="${charname}"]`).css('display', 'flex');
dragElement(newElement);
- $(`.zoomed_avatar[forChar="${charname}"] img`).on('dragstart', (e) => {
+ if (power_user.zoomed_avatar_magnification) {
+ $('.zoomed_avatar_container').izoomify();
+ } else {
+ $(`.zoomed_avatar[forChar="${charname}"] .dragClose`).hide();
+ }
+
+ $('.zoomed_avatar').on('mouseup', (e) => {
+ if (e.target.closest('.drag-grabber')) {
+ return;
+ }
+ $(`.zoomed_avatar[forChar="${charname}"]`).fadeOut(animation_duration, () => {
+ $(`.zoomed_avatar[forChar="${charname}"]`).remove();
+ });
+ });
+
+ $('.zoomed_avatar, .zoomed_avatar .dragClose').on('click touchend', (e) => {
+ if (e.target.closest('.dragClose')) {
+ $(`.zoomed_avatar[forChar="${charname}"]`).fadeOut(animation_duration, () => {
+ $(`.zoomed_avatar[forChar="${charname}"]`).remove();
+ });
+ }
+ });
+
+ zoomedAvatarImgElement.on('dragstart', (e) => {
console.log('saw drag on avatar!');
e.preventDefault();
return false;
diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js
index 35f4984b7..24d954f15 100644
--- a/public/scripts/power-user.js
+++ b/public/scripts/power-user.js
@@ -247,6 +247,7 @@ let power_user = {
encode_tags: false,
servers: [],
bogus_folders: false,
+ zoomed_avatar_magnification: false,
show_tag_filters: false,
aux_field: 'character_version',
restore_user_input: true,
@@ -1303,6 +1304,13 @@ async function applyTheme(name) {
printCharactersDebounced();
},
},
+ {
+ key: 'zoomed_avatar_magnification',
+ action: async () => {
+ $('#zoomed_avatar_magnification').prop('checked', power_user.zoomed_avatar_magnification);
+ printCharactersDebounced();
+ },
+ },
{
key: 'reduced_motion',
action: async () => {
@@ -1498,6 +1506,7 @@ function loadPowerUserSettings(settings, data) {
$('#auto_fix_generated_markdown').prop('checked', power_user.auto_fix_generated_markdown);
$('#auto_scroll_chat_to_bottom').prop('checked', power_user.auto_scroll_chat_to_bottom);
$('#bogus_folders').prop('checked', power_user.bogus_folders);
+ $('#zoomed_avatar_magnification').prop('checked', power_user.zoomed_avatar_magnification);
$(`#tokenizer option[value="${power_user.tokenizer}"]`).attr('selected', true);
$(`#send_on_enter option[value=${power_user.send_on_enter}]`).attr('selected', true);
$('#import_card_tags').prop('checked', power_user.import_card_tags);
@@ -2148,6 +2157,7 @@ async function saveTheme(name = undefined) {
hotswap_enabled: power_user.hotswap_enabled,
custom_css: power_user.custom_css,
bogus_folders: power_user.bogus_folders,
+ zoomed_avatar_magnification: power_user.zoomed_avatar_magnification,
reduced_motion: power_user.reduced_motion,
compact_input_area: power_user.compact_input_area,
};
@@ -3410,8 +3420,13 @@ $(document).ready(() => {
});
$('#bogus_folders').on('input', function () {
- const value = !!$(this).prop('checked');
- power_user.bogus_folders = value;
+ power_user.bogus_folders = !!$(this).prop('checked');
+ printCharactersDebounced();
+ saveSettingsDebounced();
+ });
+
+ $('#zoomed_avatar_magnification').on('input', function () {
+ power_user.zoomed_avatar_magnification = !!$(this).prop('checked');
printCharactersDebounced();
saveSettingsDebounced();
});
diff --git a/public/style.css b/public/style.css
index 184070c99..98bf16c5d 100644
--- a/public/style.css
+++ b/public/style.css
@@ -532,14 +532,14 @@ body.reduced-motion #bg_custom {
opacity: 1;
}
-.panelControlBar {
+body .panelControlBar {
position: absolute;
right: 5px;
top: 5px;
- margin-right: 5px;
z-index: 2000;
min-width: 55px;
justify-content: flex-end;
+ gap: 0px;
}
.panelControlBar .drag-grabber {
@@ -2226,7 +2226,7 @@ grammarly-extension {
text-align: center;
font-size: 17px;
aspect-ratio: 1 / 1;
- flex: 0.075;
+ flex: 0.05;
}
.menu_button:hover,
@@ -3805,19 +3805,33 @@ body:not(.movingUI) .drawer-content.maximized {
--leftGapWidth: calc((100vw - var(--sheldWidth)) / 2);
/* Left position of the avatar (half of the gap minus half of the avatar width) */
--leftPosition: max(0px, calc((var(--leftGapWidth) - var(--maxWidth)) / 2));
- aspect-ratio: 2 / 3;
padding: 0;
border: 0;
background-color: transparent;
max-width: var(--maxWidth);
left: var(--leftPosition);
+ position: absolute;
+ height: auto;
+ max-height: 90vh !important;
+ align-items: end;
+}
+
+.zoomed_avatar .dragClose {
+ display: none;
+}
+
+.zoomed_avatar_container {
+ width: 100%;
+ margin-inline: 10px;
+ max-height: 90vh;
+ max-width: 90svh;
}
.zoomed_avatar img {
- height: 100%;
+ height: unset !important;
width: 100%;
- vertical-align: bottom;
- object-fit: cover;
+ object-fit: contain !important;
+ border-radius: 10px;
}
/* Hide scrollbar for Chrome, Safari and Opera */