Skip to content

Commit

Permalink
v0.0.6
Browse files Browse the repository at this point in the history
添加批量缩放图片功能
  • Loading branch information
Misuzu2027 committed Nov 22, 2024
1 parent f64e3f8 commit 56921e6
Show file tree
Hide file tree
Showing 13 changed files with 320 additions and 90 deletions.
2 changes: 1 addition & 1 deletion plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "syplugin-misuzu-custom",
"author": "Misuzu2027",
"url": "https://github.com/Misuzu2027/syplugin-misuzu-custom",
"version": "0.0.5",
"version": "0.0.6",
"minAppVersion": "3.0.14",
"backends": [
"all"
Expand Down
5 changes: 4 additions & 1 deletion public/i18n/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@
"KeywordFilterNotebooksMatchSubdocuments": "Keyword Filter for Notebooks - Match Subdocuments",
"MiddleClickToggleDocTree": "Middle-click to expand/collapse notebooks or documents",
"Image": "Image",
"MiddleClickResizeImageWidth": "Middle-click to resize image width"
"MiddleClickResizeImageWidth": "Middle-click to resize image width",
"MiddleClickResizeImageWidthDesc":"Units are required. Example: 200px. px: fixed width; vw: viewport percentage.",
"ZoomWidthLoadedImagesCurrentDocument": "Zoom the width of loaded images in the current document",
"ShowTopBatchZoomBtn": "Show a batch image zoom button at the top"
}
5 changes: 4 additions & 1 deletion public/i18n/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@
"KeywordFilterNotebooksMatchSubdocuments": "关键字过滤笔记本-匹配子文档",
"MiddleClickToggleDocTree":"中键展开/折叠笔记本或文档",
"Image":"图片",
"MiddleClickResizeImageWidth":"中键图片缩放宽度"
"MiddleClickResizeImageWidth":"中键图片缩放宽度",
"MiddleClickResizeImageWidthDesc":"需要加上单位,例:200px。px:固定宽度;vw:视窗的比例。",
"ZoomWidthLoadedImagesCurrentDocument":"缩放当前文档已加载图片的宽度",
"ShowTopBatchZoomBtn":"顶部显示批量缩放图片按钮"
}
216 changes: 151 additions & 65 deletions src/components/img/ImageScalingService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@

import { EnvConfig } from "@/config/EnvConfig";
import { SettingService } from "@/service/SettingService";
import { hasClosestByTagName } from "@/utils/html-util";
import { hasClosestByTagName, isPixelOrViewportWidth } from "@/utils/html-util";
import Instance from "@/utils/Instance";
import { getActiveTab } from "@/utils/siyuan-util";
import { containsAllKeywords, splitKeywordStringToArray } from "@/utils/string-util";
import { confirmDialog, getActiveTab } from "@/utils/siyuan-util";
import { showMessage } from "siyuan";
import { isStrBlank } from "@/utils/string-util";

export class ImageScalingService {

Expand All @@ -13,84 +14,123 @@ export class ImageScalingService {
return Instance.get(ImageScalingService);
}

private topBarElement: HTMLElement;

public init() {
this.initEventListener();
// todo

// EnvConfig.ins.plugin.addTopBar({
// icon: CUSTOM_ICON_MAP.BacklinkPanelFilter.id,
// title: "缩放当前文档所有加载图片的宽度",
// position: "right",
// callback: () => {
// let currentDocument: HTMLDivElement = getActiveTab();
// if (!currentDocument) {
// return;
// }

// const docTitleElement = currentDocument.querySelector(".protyle-title");
// let docTitle = currentDocument.querySelector("div.protyle-title__input").textContent;
// let docId = docTitleElement.getAttribute("data-node-id");
// TabService.ins.openBacklinkTab(docTitle, docId, null);
// }
// });
let showTopBar = SettingService.ins.SettingConfig.topBarShowImageZoomBtn;
if (showTopBar) {
this.topBarElement = EnvConfig.ins.plugin.addTopBar({
icon: "iconContract",
title: EnvConfig.ins.plugin.i18n.ZoomWidthLoadedImagesCurrentDocument,
position: "right",
callback: () => {
let currentDocument: HTMLDivElement = getActiveTab();
if (!currentDocument) {
return;
}

const widthInput = document.createElement("input");
widthInput.className = "b3-text-field fn__block";

confirmDialog(EnvConfig.ins.plugin.i18n.ZoomWidthLoadedImagesCurrentDocument
, widthInput, (): boolean => {
return batchUpdateCurDocImageWidth(widthInput.value);
});
}
});
} else {
if (this.topBarElement) {
let topBarElements = EnvConfig.ins.plugin.topBarIcons;
for (let i = 0; i < topBarElements.length; i++) {
if (topBarElements[i].id === this.topBarElement.id) {
this.topBarElement.remove();

topBarElements.splice(i, 1); // 删除当前元素
i--; // 调整索引以避免跳过下一个元素
break;
}
}
}

}
}

public destroy() {

}

public initEventListener() {
document.body.addEventListener('mousedown', function (event: MouseEvent) {
if (event.button != 1) return;
// 图片宽度,目前思源只支持 px,vw。
let imageWidthValue = SettingService.ins.SettingConfig.imageMiddleClickResizeWidth;;
if (!imageWidthValue) {
return;
}
let clickElement = event.target as HTMLElement;
// 检查点击的元素是否是图片
if (!clickElement.matches('.protyle-wysiwyg div[data-node-id] span.img[data-type="img"] img')) {
return;
}
let imageSpanElement = clickElement.parentElement.parentElement;
// 如果图片在表格中,也不进行设置
if (imageSpanElement.parentElement.tagName.toLowerCase() === "td") {
// return;
}
let layoutTabContainerElement = clickElement.parentElement;
let classFlag = "misuzu2027__image_zoom_mousedown";
if (document.body.matches(`.${classFlag}`)) {
return;
}
document.body.classList.add("misuzu2027__image_zoom_mousedown")
document.body.addEventListener('mousedown', handleImageZoomMousedown);
}

// // 循环查找当前点击的文档元素
while (layoutTabContainerElement) {
if (layoutTabContainerElement.tagName.toLowerCase() === 'div'
&& layoutTabContainerElement.classList.contains('protyle')
&& layoutTabContainerElement.classList.contains('fn__flex-1')) {
break;
}
layoutTabContainerElement = layoutTabContainerElement.parentElement;
}
// 默认只读模式
let isReadonly = true;
if (layoutTabContainerElement) {
let readonlyButton = layoutTabContainerElement.querySelector('[data-type="readonly"]');
if (readonlyButton) {
isReadonly = readonlyButton.querySelector("use").getAttribute("xlink:href") !== "#iconUnlock";
}
}
if (isReadonly) {
console.log("点击自动设置图片宽度失败!当前是只读模式。图片地址:" + clickElement.getAttribute("src"));
return;
}
zoomImageWith(event, imageWidthValue)
});
}

function handleImageZoomMousedown(event: MouseEvent) {

if (event.button != 1) return;
let imageWidthValue = SettingService.ins.SettingConfig.imageMiddleClickResizeWidth;
if (isStrBlank(imageWidthValue)) {
// showImageFaileMessage("宽度为空");
return;
}
let clickElement = event.target as HTMLElement;
// 检查点击的元素是否是图片
if (!clickElement.matches('.protyle-wysiwyg div[data-node-id] span.img[data-type="img"] img')) {
return;
}
let imageSpanElement = clickElement.parentElement.parentElement;
// 如果图片在表格中,也不进行设置
if (imageSpanElement.parentElement.tagName.toLowerCase() === "td") {
// return;
}
let layoutTabContainerElement = clickElement.parentElement;

// 图片宽度,目前思源只支持 px,vw。
if (!isPixelOrViewportWidth(imageWidthValue)) {
showImageFaileMessage("宽度格式不正确");
return;
}

// // 循环查找当前点击的文档元素
while (layoutTabContainerElement) {
if (layoutTabContainerElement.tagName.toLowerCase() === 'div'
&& layoutTabContainerElement.classList.contains('protyle')
&& layoutTabContainerElement.classList.contains('fn__flex-1')) {
break;
}
layoutTabContainerElement = layoutTabContainerElement.parentElement;
}
// 默认只读模式
let isReadonly = true;
if (layoutTabContainerElement) {
let readonlyButton = layoutTabContainerElement.querySelector('[data-type="readonly"]');
if (readonlyButton) {
isReadonly = readonlyButton.querySelector("use").getAttribute("xlink:href") !== "#iconUnlock";
}
}
if (isReadonly) {
console.log("点击自动设置图片宽度失败!当前是只读模式。图片地址:" + clickElement.getAttribute("src"));
event.preventDefault();
return;
}
let flag = zoomImageWith(event.target as HTMLElement, imageWidthValue);
if (flag) {
event.preventDefault();
}

}


function zoomImageWith(event: MouseEvent, width: string) {
let target = event.target as HTMLElement;


function zoomImageWith(target: HTMLElement, width: string): boolean {
// 创建一个 mousedown 事件
const mouseDownEvent = new MouseEvent('mousedown', {
bubbles: true, // 事件是否冒泡
Expand All @@ -113,10 +153,9 @@ function zoomImageWith(event: MouseEvent, width: string) {
return;
}
dragElement.dispatchEvent(mouseDownEvent);
event.preventDefault();
imgElement.style.width = width;

dragElement.dispatchEvent(mouseUpEvent);
return true;
}

function zoomImageWithMiddleClick() {
Expand Down Expand Up @@ -227,4 +266,51 @@ function zoomImageWithMiddleClick() {

});

}


function batchUpdateCurDocImageWidth(width: string): boolean {
if (isStrBlank(width)) {
showImageFaileMessage("宽度为空");
return;
}
if (!isPixelOrViewportWidth(width)) {
showImageFaileMessage("宽度格式不正确");
return;
}
let currentDocument: HTMLDivElement = getActiveTab();
if (!currentDocument) {
showImageFaileMessage("没找到打开的文档");
return;
}
// 默认只读模式
let isReadonly = true;
let readonlyButton = currentDocument.querySelector('[data-type="readonly"]');
if (readonlyButton) {
isReadonly = readonlyButton.querySelector("use").getAttribute("xlink:href") !== "#iconUnlock";
}
if (isReadonly) {
showImageFaileMessage("当前文档为只读模式");
return;
}

let imageElementList = currentDocument.querySelectorAll(`.protyle-wysiwyg div[data-node-id] span.img[data-type="img"] img`);
for (let element of imageElementList) {

let hasTable = hasClosestByTagName(element as HTMLElement, "TD");
// 如果图片在表格中,也不进行设置
if (hasTable) {
continue;
}
zoomImageWith(element as HTMLElement, width);
}
return true;
}

function showImageFaileMessage(reason: string) {
showMessage(
`批量设置当前文档图片宽度失败 : ${reason}!`,
4000,
"info",
);
}
60 changes: 60 additions & 0 deletions src/components/img/input-width-dialog.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!-- <script lang="ts">
// import { EnvConfig } from "@/config/EnvConfig";
import { createEventDispatcher, onMount } from "svelte";
import { SettingService } from "@/service/SettingService";
const dispatch = createEventDispatcher();
let width: string =
SettingService.ins.SettingConfig.imageMiddleClickResizeWidth;
// let rootElement: HTMLElement;
onMount(async () => {});
function cancelBtnClick() {
dispatch("cancel", null);
}
function confirmBtnClick() {
dispatch("confirm", {
width: width,
});
}
</script>
<div class="b3-dialog__body">
<div class="b3-dialog__content">
<div class="ft__breakword">
<input
class="b3-text-field fn__block misuzu2027__copy misuzu2027__protyle-custom"
type="text"
bind:value={width}
/>
</div>
</div>
<div class="b3-dialog__action">
<button class="b3-button b3-button--cancel" on:click={cancelBtnClick}
>取消</button
>
<div class="fn__space"></div>
<button class="b3-button b3-button--text" on:click={confirmBtnClick}
>确定</button
>
</div>
</div>
<style>
input {
margin-top: -1px;
margin-left: 30px;
width: 100px;
height: 25px;
font-size: 85%;
font-weight: bold;
background-color: rgba(128, 128, 128, 0);
}
input:focus {
background-color: var(--b3-theme-background);
}
</style> -->
2 changes: 1 addition & 1 deletion src/components/setting/setting-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import SettingPageSvelte from "@/components/setting/setting-page.svelte"
export function openSettingsDialog() {
let isMobile = EnvConfig.ins.isMobile;
// 生成Dialog内容
const dialogId = "backlink-panel-setting-" + Date.now();
const dialogId = "misuzu2027-setting-" + Date.now();
// 创建dialog
const settingDialog = new Dialog({
title: EnvConfig.ins.i18n.PluginSettings,
Expand Down
18 changes: 9 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ export default class PluginSample extends Plugin {
}
}

this.eventBus.on('switch-protyle', (e: any) => {
EnvConfig.ins.lastViewedDocId = e.detail.protyle.block.rootID;
})
this.eventBus.on('loaded-protyle-static', (e: any) => {
// console.log("index loaded-protyle-static ")
if (EnvConfig.ins.isMobile && !EnvConfig.ins.lastViewedDocId) {
EnvConfig.ins.lastViewedDocId = e.detail.protyle.block.rootID;
}
})
// this.eventBus.on('switch-protyle', (e: any) => {
// EnvConfig.ins.lastViewedDocId = e.detail.protyle.block.rootID;
// })
// this.eventBus.on('loaded-protyle-static', (e: any) => {
// // console.log("index loaded-protyle-static ")
// if (EnvConfig.ins.isMobile && !EnvConfig.ins.lastViewedDocId) {
// EnvConfig.ins.lastViewedDocId = e.detail.protyle.block.rootID;
// }
// })
}


Expand Down
Loading

0 comments on commit 56921e6

Please sign in to comment.