2020-08-14 14:37:10 +02:00
//META{"name":"ImageUtilities","authorId":"278543574059057154","invite":"Jx3TjNS","donate":"https://www.paypal.me/MircoWittrien","patreon":"https://www.patreon.com/MircoWittrien","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ImageUtilities","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ImageUtilities/ImageUtilities.plugin.js"}*//
var ImageUtilities = ( _ => {
const imgUrlReplaceString = "DEVILBRO_BD_REVERSEIMAGESEARCH_REPLACE_IMAGEURL" ;
2020-08-15 10:38:15 +02:00
var firedEvents = [ ] , clickedImage ;
2020-08-14 15:18:33 +02:00
var settings = { } , inputs = { } , amounts = { } , zoomSettings = { } , engines = { } , enabledEngines = { } ;
const ImageDetails = class ImageDetails extends BdApi . React . Component {
componentDidMount ( ) {
this . props . attachment = BDFDB . ReactUtils . findValue ( BDFDB . ReactUtils . getValue ( this , "_reactInternalFiber.return" ) , "attachment" , { up : true } ) ;
BDFDB . ReactUtils . forceUpdate ( this ) ;
}
componentDidUpdate ( ) {
if ( ( ! this . props . attachment || ! this . props . attachment . size ) && ! this . props . loaded ) {
this . props . loaded = true ;
this . props . attachment = BDFDB . ReactUtils . findValue ( BDFDB . ReactUtils . getValue ( this , "_reactInternalFiber.return" ) , "attachment" , { up : true } ) ;
BDFDB . ReactUtils . forceUpdate ( this ) ;
}
}
render ( ) {
return ! this . props . attachment ? null : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex , {
2020-08-14 15:26:54 +02:00
className : BDFDB . disCN . _imageutilitiesimagedetails ,
2020-08-14 15:18:33 +02:00
children : [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex . Child , {
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Anchor , {
title : this . props . original ,
href : this . props . original ,
children : this . props . attachment . filename ,
onClick : event => {
BDFDB . ListenerUtils . stopEvent ( event ) ;
BDFDB . DiscordUtils . openLink ( this . props . original ) ;
}
} )
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex . Child , {
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
children : BDFDB . NumberUtils . formatBytes ( this . props . attachment . size )
} )
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex . Child , {
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
children : ` ${ this . props . attachment . width } x ${ this . props . attachment . height } px `
} )
} )
]
} ) ;
}
} ;
2020-08-14 14:37:10 +02:00
return class ImageUtilities {
getName ( ) { return "ImageUtilities" ; }
2020-08-26 13:18:25 +02:00
getVersion ( ) { return "4.1.0" ; }
2020-08-14 14:37:10 +02:00
getAuthor ( ) { return "DevilBro" ; }
getDescription ( ) { return "Adds a handful of options for images/emotes/avatars (direct download, reverse image search, zoom, copy image link, copy image to clipboard, gallery mode)" ; }
constructor ( ) {
2020-08-14 16:05:53 +02:00
this . changelog = {
2020-08-14 20:10:13 +02:00
"progress" : [ [ "Welcome" , "This is the successor of ImageZoom, ImageGallery, ReverseImageSearch and ShowImageDetails. All of these plugins are now combined in one with even more useful features. Check out the plugin settings to configure the plugin the way you want it to work." ] ] ,
2020-08-24 21:10:15 +02:00
"improved" : [ [ "Animated Icons/Avatars" , "Right clicking a server/user with an animated icon will now give the option to either choose the .png or .gif" ] ] ,
2020-08-20 14:20:57 +02:00
"fixed" : [ [ "Image Formats" , "Fixed some issues with some image formats, like copy option not showing for gifs since gifs can't be copied in the clipboard" ] ]
2020-08-14 16:05:53 +02:00
} ;
2020-08-14 14:37:10 +02:00
this . patchedModules = {
after : {
ImageModal : [ "render" , "componentDidMount" ] ,
2020-08-14 15:26:54 +02:00
LazyImage : [ "render" , "componentDidMount" ]
2020-08-14 14:37:10 +02:00
}
} ;
}
initConstructor ( ) {
2020-08-15 10:38:15 +02:00
firedEvents = [ ] ;
2020-08-14 14:37:10 +02:00
clickedImage = null ;
this . defaults = {
settings : {
2020-08-14 20:10:13 +02:00
addDetails : { value : true , inner : false , description : "Add Image details (name, size, amount) in the Image Modal" } ,
2020-08-20 14:20:57 +02:00
showAsHeader : { value : true , inner : false , description : "Show Image details as a details header above the Image in the chat" } ,
2020-08-14 15:26:54 +02:00
showOnHover : { value : false , inner : false , description : "Show Image details as Tooltip in the chat" } ,
2020-08-14 20:10:13 +02:00
enableGallery : { value : true , inner : false , description : "Displays previous/next Images in the same message in the Image Modal" } ,
enableZoom : { value : true , inner : false , description : "Creates a zoom lense if you press down on an Image in the Image Modal" } ,
enableCopyImg : { value : true , inner : false , description : "Add a copy Image option in the Image Modal" } ,
2020-08-14 14:37:10 +02:00
useChromium : { value : false , inner : false , description : "Use an inbuilt browser window instead of opening your default browser" } ,
addUserAvatarEntry : { value : true , inner : true , description : "User Avatars" } ,
addGuildIconEntry : { value : true , inner : true , description : "Server Icons" } ,
addEmojiEntry : { value : true , inner : true , description : "Custom Emojis/Emotes" }
} ,
2020-08-14 15:18:33 +02:00
amounts : {
hoverDelay : { value : 0 , min : 0 , description : "Image Tooltip delay in millisec:" }
} ,
2020-08-14 14:37:10 +02:00
inputs : {
downloadLocation : { value : "" , childProps : { type : "file" , searchFolders : true } , description : "Download Location" } ,
} ,
zoomSettings : {
2020-08-15 10:38:15 +02:00
zoomlevel : { value : 2 , digits : 1 , minValue : 1 , maxValue : 20 , unit : "x" , label : "ACCESSIBILITY_ZOOM_LEVEL_LABEL" } ,
lensesize : { value : 200 , digits : 0 , minValue : 50 , maxValue : 5000 , unit : "px" , label : "context_lensesize_text" }
2020-08-14 14:37:10 +02:00
} ,
engines : {
_all : { value : true , name : BDFDB . LanguageUtils . LanguageStrings . FORM _LABEL _ALL , url : null } ,
Baidu : { value : true , name : "Baidu" , url : "http://image.baidu.com/pcdutu?queryImageUrl=" + imgUrlReplaceString } ,
Bing : { value : true , name : "Bing" , url : "https://www.bing.com/images/search?q=imgurl:" + imgUrlReplaceString + "&view=detailv2&iss=sbi&FORM=IRSBIQ" } ,
Google : { value : true , name : "Google" , url : "https://images.google.com/searchbyimage?image_url=" + imgUrlReplaceString } ,
IQDB : { value : true , name : "IQDB" , url : "https://iqdb.org/?url=" + imgUrlReplaceString } ,
Reddit : { value : true , name : "Reddit" , url : "http://karmadecay.com/search?q=" + imgUrlReplaceString } ,
SauceNAO : { value : true , name : "SauceNAO" , url : "https://saucenao.com/search.php?db=999&url=" + imgUrlReplaceString } ,
Sogou : { value : true , name : "Sogou" , url : "http://pic.sogou.com/ris?flag=1&drag=0&query=" + imgUrlReplaceString + "&flag=1" } ,
TinEye : { value : true , name : "TinEye" , url : "https://tineye.com/search?url=" + imgUrlReplaceString } ,
WhatAnime : { value : true , name : "WhatAnime" , url : "https://trace.moe/?url=" + imgUrlReplaceString } ,
Yandex : { value : true , name : "Yandex" , url : "https://yandex.com/images/search?url=" + imgUrlReplaceString + "&rpt=imageview" }
}
} ;
this . css = `
2020-08-14 15:26:54 +02:00
$ { BDFDB . dotCN . _imageutilitiesimagedetails } {
margin : 5 px 0 ;
}
$ { BDFDB . dotCNS . spoilerhidden + BDFDB . dotCN . _imageutilitiesimagedetails } {
visibility : hidden ;
max - width : 1 px ;
}
2020-08-14 21:59:05 +02:00
$ { BDFDB . dotCN . _imageutilitiesdetailsadded } : not ( [ style *= "opacity: 0;" ] ) {
2020-08-14 14:37:10 +02:00
transform : unset ! important ;
}
$ { BDFDB . dotCN . _imageutilitiessibling } {
display : flex ;
align - items : center ;
position : fixed ;
top : 50 % ;
bottom : 50 % ;
cursor : pointer ;
}
$ { BDFDB . dotCN . _imageutilitiesprevious } {
justify - content : flex - end ;
right : 90 % ;
}
$ { BDFDB . dotCN . _imageutilitiesnext } {
justify - content : flex - start ;
left : 90 % ;
}
$ { BDFDB . dotCN . _imageutilitiesswitchicon } {
position : absolute ;
background : rgba ( 0 , 0 , 0 , 0.3 ) ;
border - radius : 50 % ;
padding : 15 px ;
transition : all 0.3 s ease ;
}
$ { BDFDB . dotCNS . _imageutilitiesprevious + BDFDB . dotCN . _imageutilitiesswitchicon } {
right : 10 px ;
}
$ { BDFDB . dotCNS . _imageutilitiesnext + BDFDB . dotCN . _imageutilitiesswitchicon } {
left : 10 px ;
}
$ { BDFDB . dotCN . _imageutilitiessibling } : hover $ { BDFDB . dotCN . _imageutilitiesswitchicon } {
background : rgba ( 0 , 0 , 0 , 0.5 ) ;
}
$ { BDFDB . dotCN . _imageutilitiesdetailswrapper } {
position : fixed ;
bottom : 10 px ;
left : 15 px ;
right : 15 px ;
pointer - events : none ;
}
$ { BDFDB . dotCN . _imageutilitiesdetails } {
margin - top : 5 px ;
font - size : 14 px ;
font - weight : 500 ;
}
$ { BDFDB . dotCN . _imageutilitiesdetailslabel } {
font - weight : 600 ;
}
$ { BDFDB . dotCN . _imageutilitieslense } {
border : 2 px solid rgb ( 114 , 137 , 218 ) ;
}
$ { BDFDB . dotCN . _imageutilitiesoperations } {
position : absolute ;
display : flex ;
}
$ { BDFDB . dotCNS . _imageutilitiesoperations + BDFDB . dotCN . downloadlink } {
position : relative ! important ;
white - space : nowrap ! important ;
}
$ { BDFDB . dotCNS . _imageutilitiesoperations + BDFDB . dotCN . anchor + BDFDB . dotCN . downloadlink } {
margin : 0 ! important ;
}
` ;
}
getSettingsPanel ( collapseStates = { } ) {
if ( ! window . BDFDB || typeof BDFDB != "object" || ! BDFDB . loaded || ! this . started ) return ;
let settingsPanel , settingsItems = [ ] ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : "Settings" ,
collapseStates : collapseStates ,
children : Object . keys ( settings ) . map ( key => ! this . defaults . settings [ key ] . inner && BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
className : BDFDB . disCN . marginbottom8 ,
type : "Switch" ,
plugin : this ,
keys : [ "settings" , key ] ,
label : this . defaults . settings [ key ] . description ,
value : settings [ key ]
2020-08-14 15:18:33 +02:00
} ) ) . concat ( Object . keys ( amounts ) . map ( key => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
className : BDFDB . disCN . marginbottom8 ,
type : "TextInput" ,
plugin : this ,
keys : [ "amounts" , key ] ,
label : this . defaults . amounts [ key ] . description ,
basis : "50%" ,
childProps : { type : "number" } ,
min : this . defaults . amounts [ key ] . min ,
max : this . defaults . amounts [ key ] . max ,
value : amounts [ key ]
} ) ) ) . concat ( Object . keys ( inputs ) . map ( key => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
2020-08-14 14:37:10 +02:00
className : BDFDB . disCN . marginbottom8 ,
type : "TextInput" ,
plugin : this ,
keys : [ "inputs" , key ] ,
label : this . defaults . inputs [ key ] . description ,
basis : "70%" ,
childProps : this . defaults . inputs [ key ] . childProps ,
value : key == "downloadLocation" ? this . getDownloadLocation ( ) : inputs [ key ]
} ) ) ) . filter ( n => n )
} ) ) ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : "Context Menu Entries" ,
collapseStates : collapseStates ,
children : [ BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . FormComponents . FormTitle , {
className : BDFDB . disCN . marginbottom4 ,
tag : BDFDB . LibraryComponents . FormComponents . FormTitle . Tags . H3 ,
children : "Add additional Context Menu Entry for:"
} ) ] . concat ( Object . keys ( settings ) . map ( key => this . defaults . settings [ key ] . inner && BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
className : BDFDB . disCN . marginbottom8 ,
type : "Switch" ,
plugin : this ,
keys : [ "settings" , key ] ,
label : this . defaults . settings [ key ] . description ,
value : settings [ key ]
} ) ) )
} ) ) ;
settingsItems . push ( BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . CollapseContainer , {
title : "Search Engines" ,
collapseStates : collapseStates ,
children : Object . keys ( engines ) . filter ( n => n && n != "_all" ) . map ( key => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SettingsSaveItem , {
className : BDFDB . disCN . marginbottom8 ,
type : "Switch" ,
plugin : this ,
keys : [ "engines" , key ] ,
label : this . defaults . engines [ key ] . name ,
value : engines [ key ]
} ) )
} ) ) ;
return settingsPanel = BDFDB . PluginUtils . createSettingsPanel ( this , settingsItems ) ;
}
// Legacy
2020-08-21 16:17:47 +02:00
load ( ) {
if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) BDFDB . PluginUtils . load ( this ) ;
}
2020-08-14 14:37:10 +02:00
start ( ) {
if ( ! window . BDFDB ) window . BDFDB = { myPlugins : { } } ;
if ( window . BDFDB && window . BDFDB . myPlugins && typeof window . BDFDB . myPlugins == "object" ) window . BDFDB . myPlugins [ this . getName ( ) ] = this ;
let libraryScript = document . querySelector ( "head script#BDFDBLibraryScript" ) ;
if ( ! libraryScript || ( performance . now ( ) - libraryScript . getAttribute ( "date" ) ) > 600000 ) {
if ( libraryScript ) libraryScript . remove ( ) ;
libraryScript = document . createElement ( "script" ) ;
libraryScript . setAttribute ( "id" , "BDFDBLibraryScript" ) ;
libraryScript . setAttribute ( "type" , "text/javascript" ) ;
libraryScript . setAttribute ( "src" , "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.min.js" ) ;
libraryScript . setAttribute ( "date" , performance . now ( ) ) ;
libraryScript . addEventListener ( "load" , _ => { this . initialize ( ) ; } ) ;
document . head . appendChild ( libraryScript ) ;
}
else if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) this . initialize ( ) ;
this . startTimeout = setTimeout ( _ => {
try { return this . initialize ( ) ; }
catch ( err ) { console . error ( ` %c[ ${ this . getName ( ) } ]%c ` , "color: #3a71c1; font-weight: 700;" , "" , "Fatal Error: Could not initiate plugin! " + err ) ; }
} , 30000 ) ;
}
initialize ( ) {
if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
if ( this . started ) return ;
BDFDB . PluginUtils . init ( this ) ;
BDFDB . ListenerUtils . add ( this , document . body , "click" , BDFDB . dotCNS . message + BDFDB . dotCNS . imagewrapper + "img" , e => {
clickedImage = e . target ;
BDFDB . TimeUtils . timeout ( _ => { clickedImage = null ; } ) ;
} ) ;
2020-08-14 15:26:54 +02:00
BDFDB . ModuleUtils . patch ( this , ( BDFDB . ModuleUtils . findByName ( "renderImageComponent" , false ) . exports || { } ) , "renderImageComponent" , { after : e => {
if ( e . returnValue && e . returnValue . type && ( e . returnValue . type . displayName == "LazyImageZoomable" || e . returnValue . type . displayName == "LazyImage" ) && e . methodArguments [ 0 ] . original && e . methodArguments [ 0 ] . src . indexOf ( "https://media.discordapp.net/attachments" ) == 0 ) return this . injectImageDetails ( e . methodArguments [ 0 ] , e . returnValue ) ;
} } ) ;
2020-08-14 14:37:10 +02:00
this . forceUpdateAll ( ) ;
}
else console . error ( ` %c[ ${ this . getName ( ) } ]%c ` , "color: #3a71c1; font-weight: 700;" , "" , "Fatal Error: Could not load BD functions!" ) ;
}
stop ( ) {
if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
this . stopping = true ;
2020-08-15 10:38:15 +02:00
this . cleanupListeners ( "Gallery" ) ;
this . cleanupListeners ( "Zoom" ) ;
2020-08-14 14:37:10 +02:00
this . forceUpdateAll ( ) ;
BDFDB . PluginUtils . clear ( this ) ;
}
}
// Begin of own functions
onSettingsClosed ( ) {
if ( this . SettingsUpdated ) {
delete this . SettingsUpdated ;
this . forceUpdateAll ( ) ;
}
}
onGuildContextMenu ( e ) {
2020-08-26 13:18:25 +02:00
if ( e . instance . props . guild && settings . addGuildIconEntry ) this . injectItem ( e , e . instance . props . guild . getIconURL ( "png" ) , BDFDB . LibraryModules . IconUtils . hasAnimatedGuildIcon ( e . instance . props . guild ) && e . instance . props . guild . getIconURL ( "gif" ) ) ;
2020-08-14 14:37:10 +02:00
}
onUserContextMenu ( e ) {
2020-08-24 21:10:15 +02:00
if ( e . instance . props . user && settings . addUserAvatarEntry ) this . injectItem ( e , e . instance . props . user . getAvatarURL ( "png" ) , BDFDB . LibraryModules . IconUtils . hasAnimatedAvatar ( e . instance . props . user ) && e . instance . props . user . getAvatarURL ( "gif" ) )
2020-08-14 14:37:10 +02:00
}
onNativeContextMenu ( e ) {
if ( e . type == "NativeImageContextMenu" && ( e . instance . props . href || e . instance . props . src ) ) {
this . injectItem ( e , e . instance . props . href || e . instance . props . src ) ;
}
}
onMessageContextMenu ( e ) {
if ( e . instance . props . message && e . instance . props . channel && e . instance . props . target ) {
if ( e . instance . props . attachment ) this . injectItem ( e , e . instance . props . attachment . url ) ;
else if ( e . instance . props . target . tagName == "A" && e . instance . props . message . embeds && e . instance . props . message . embeds [ 0 ] && e . instance . props . message . embeds [ 0 ] . type == "image" ) this . injectItem ( e , e . instance . props . target . href ) ;
else if ( e . instance . props . target . tagName == "IMG" ) {
if ( BDFDB . DOMUtils . containsClass ( e . instance . props . target . parentElement , BDFDB . disCN . imagewrapper ) ) this . injectItem ( e , e . instance . props . target . src ) ;
else if ( BDFDB . DOMUtils . containsClass ( e . instance . props . target , BDFDB . disCN . embedauthoricon ) && settings . addUserAvatarEntry ) this . injectItem ( e , e . instance . props . target . src ) ;
2020-08-16 19:05:39 +02:00
else if ( BDFDB . DOMUtils . containsClass ( e . instance . props . target , BDFDB . disCN . emojiold , "emote" , false ) && settings . addEmojiEntry ) this . injectItem ( e , e . instance . props . target . src ) ;
}
else {
let reaction = BDFDB . DOMUtils . getParent ( BDFDB . dotCN . messagereaction , e . instance . props . target ) ;
if ( reaction && settings . addEmojiEntry ) this . injectItem ( e , reaction . querySelector ( BDFDB . dotCN . emojiold ) . src ) ;
2020-08-14 14:37:10 +02:00
}
}
}
2020-08-24 21:10:15 +02:00
injectItem ( e , ... urls ) {
let types = [ ] ;
let validUrls = urls . filter ( n => this . isValidImg ( n ) ) . map ( n => {
let url = n . replace ( /^url\(|\)$|"|'/g , "" ) . replace ( /\?size\=\d+$/ , "?size=4096" ) . replace ( /[\?\&](height|width)=\d+/g , "" ) ;
2020-08-14 14:37:10 +02:00
if ( url . indexOf ( "https://images-ext-1.discordapp.net/external/" ) > - 1 ) {
2020-08-24 21:10:15 +02:00
if ( url . split ( "/https/" ) . length > 1 ) url = "https://" + url . split ( "/https/" ) . pop ( ) ;
else if ( url . split ( "/http/" ) . length > 1 ) url = "http://" + url . split ( "/http/" ) . pop ( ) ;
2020-08-14 14:37:10 +02:00
}
2020-08-24 21:10:15 +02:00
const file = url && ( BDFDB . LibraryModules . URLParser . parse ( url ) . pathname || "" ) . toLowerCase ( ) ;
const type = file && file . split ( "." ) . pop ( ) ;
return url && type && ! types . includes ( type ) && types . push ( type ) && { url , type } ;
} ) . filter ( n => n ) ;
if ( ! validUrls . length ) return ;
let [ children , index ] = BDFDB . ContextMenuUtils . findItem ( e . returnvalue , { id : "devmode-copy-id" , group : true } ) ;
children . splice ( index > - 1 ? index : children . length , 0 , BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuGroup , {
children : BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
label : "Image Utilities" ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "main-subitem" ) ,
2020-08-25 00:17:15 +02:00
children : validUrls . length == 1 ? this . createUrlMenu ( e , validUrls [ 0 ] . url ) : validUrls . map ( ( urlData , i ) => BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
2020-08-24 21:10:15 +02:00
label : urlData . type . toUpperCase ( ) ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "subitem" , i ) ,
2020-08-25 00:17:15 +02:00
children : this . createUrlMenu ( e , urlData . url )
2020-08-24 21:10:15 +02:00
} ) )
} )
} ) ) ;
}
2020-08-25 00:17:15 +02:00
createUrlMenu ( e , url ) {
2020-08-24 21:10:15 +02:00
let enginesWithoutAll = BDFDB . ObjectUtils . filter ( enabledEngines , n => n != "_all" , true ) ;
let engineKeys = Object . keys ( enginesWithoutAll ) ;
return [
BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
label : this . labels . context _viewimage _text ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "view-image" ) ,
action : _ => {
let img = new Image ( ) ;
img . onload = function ( ) {
BDFDB . LibraryModules . ModalUtils . openModal ( modalData => {
return BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ModalComponents . ModalRoot , Object . assign ( {
className : BDFDB . disCN . imagemodal
} , modalData , {
size : BDFDB . LibraryComponents . ModalComponents . ModalSize . DYNAMIC ,
"aria-label" : BDFDB . LanguageUtils . LanguageStrings . IMAGE ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . ImageModal , {
src : url ,
original : url ,
width : this . width ,
height : this . height ,
className : BDFDB . disCN . imagemodalimage ,
shouldAnimate : true ,
renderLinkComponent : props => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Anchor , props )
} )
} ) , true ) ;
} ) ;
} ;
img . src = url ;
}
} ) ,
BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
label : this . labels . context _saveimage _text ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "download-image" ) ,
action : _ => {
BDFDB . LibraryRequires . request ( url , { encoding : null } , ( error , response , body ) => {
let path = this . getDownloadLocation ( ) ;
if ( error ) BDFDB . NotificationUtils . toast ( this . labels . toast _saveimage _failed . replace ( "{{path}}" , path ) , { type : "error" } ) ;
else {
BDFDB . LibraryRequires . fs . writeFile ( this . getFileName ( path , url . split ( "/" ) . pop ( ) . split ( "." ) . slice ( 0 , - 1 ) . join ( "." ) , response . headers [ "content-type" ] . split ( "/" ) . pop ( ) . split ( "+" ) [ 0 ] , 0 ) , body , error => {
if ( error ) BDFDB . NotificationUtils . toast ( this . labels . toast _saveimage _failed . replace ( "{{path}}" , path ) , { type : "error" } ) ;
else BDFDB . NotificationUtils . toast ( this . labels . toast _saveimage _success . replace ( "{{path}}" , path ) , { type : "success" } ) ;
} ) ;
}
} ) ;
}
} ) ,
! this . isCopyable ( url ) ? null : BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
label : this . labels . context _copyimage _text ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "copy-image" ) ,
action : _ => {
this . copyImage ( url ) ;
}
} ) ,
BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
label : this . labels . context _copyimagelink _text ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "copy-src" ) ,
action : _ => {
BDFDB . LibraryRequires . electron . clipboard . write ( { text : url } ) ;
BDFDB . NotificationUtils . toast ( this . labels . toast _copyimagelink _success , { type : "success" } ) ;
}
} ) ,
! this . isSearchable ( url ) ? null : engineKeys . length == 1 ? BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
label : this . labels . context _reverseimagesearch _text . replace ( "..." , this . defaults . engines [ engineKeys [ 0 ] ] . name ) ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "single-search" ) ,
persisting : true ,
action : event => {
if ( ! event . shiftKey ) BDFDB . ContextMenuUtils . close ( e . instance ) ;
BDFDB . DiscordUtils . openLink ( this . defaults . engines [ engineKeys [ 0 ] ] . url . replace ( imgUrlReplaceString , encodeURIComponent ( url ) ) , settings . useChromium , event . shiftKey ) ;
}
} ) : BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
label : this . labels . context _reverseimagesearch _text ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "submenu-search" ) ,
children : ! engineKeys . length ? BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
label : this . labels . submenu _disabled _text ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "disabled" ) ,
disabled : true
} ) : Object . keys ( enabledEngines ) . map ( key => BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuItem , {
label : this . defaults . engines [ key ] . name ,
id : BDFDB . ContextMenuUtils . createItemId ( this . name , "search" , key ) ,
color : key == "_all" ? BDFDB . LibraryComponents . MenuItems . Colors . DANGER : BDFDB . LibraryComponents . MenuItems . Colors . DEFAULT ,
persisting : true ,
action : event => {
if ( ! event . shiftKey ) BDFDB . ContextMenuUtils . close ( e . instance ) ;
if ( key == "_all" ) {
for ( let key2 in enginesWithoutAll ) BDFDB . DiscordUtils . openLink ( this . defaults . engines [ key2 ] . url . replace ( imgUrlReplaceString , encodeURIComponent ( url ) ) , settings . useChromium , event . shiftKey ) ;
}
else BDFDB . DiscordUtils . openLink ( this . defaults . engines [ key ] . url . replace ( imgUrlReplaceString , encodeURIComponent ( url ) ) , settings . useChromium , event . shiftKey ) ;
}
} ) )
} )
] . filter ( n => n ) ;
2020-08-14 14:37:10 +02:00
}
processImageModal ( e ) {
if ( clickedImage ) e . instance . props . cachedImage = clickedImage ;
2020-08-20 14:20:57 +02:00
let url = e . instance . props . cachedImage && e . instance . props . cachedImage . src ? e . instance . props . cachedImage : e . instance . props . src ;
url = url . src || url ;
let messages = this . getMessageGroupOfImage ( url ) ;
2020-08-14 14:37:10 +02:00
if ( e . returnvalue ) {
let [ children , index ] = BDFDB . ReactUtils . findParent ( e . returnvalue , { props : [ [ "className" , BDFDB . disCN . downloadlink ] ] } ) ;
if ( index > - 1 ) {
let openContext = event => {
BDFDB . ContextMenuUtils . open ( this , event , BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuGroup , {
children : Object . keys ( zoomSettings ) . map ( type => BDFDB . ContextMenuUtils . createItem ( BDFDB . LibraryComponents . MenuItems . MenuSliderItem , Object . assign ( {
id : BDFDB . ContextMenuUtils . createItemId ( this . name , type ) ,
value : zoomSettings [ type ] ,
renderLabel : value => {
return ( this . labels [ this . defaults . zoomSettings [ type ] . label ] || BDFDB . LanguageUtils . LanguageStrings [ this . defaults . zoomSettings [ type ] . label ] ) + ": " + value + this . defaults . zoomSettings [ type ] . unit ;
} ,
onValueRender : value => {
return value + this . defaults . zoomSettings [ type ] . unit ;
} ,
onValueChange : value => {
zoomSettings [ type ] = value ;
BDFDB . DataUtils . save ( zoomSettings , this , "zoomSettings" ) ;
}
} , BDFDB . ObjectUtils . extract ( this . defaults . zoomSettings [ type ] , "digits" , "minValue" , "maxValue" ) ) ) )
} ) ) ;
} ;
2020-08-20 14:20:57 +02:00
let isVideo = ( typeof e . instance . props . children == "function" && e . instance . props . children ( Object . assign ( { } , e . instance . props , { size : e . instance . props } ) ) || { type : { } } ) . type . displayName == "Video" ;
2020-08-14 14:37:10 +02:00
children [ index ] = BDFDB . ReactUtils . createElement ( "span" , {
className : BDFDB . disCN . _imageutilitiesoperations ,
children : [
children [ index ] ,
2020-08-20 14:20:57 +02:00
settings . enableCopyImg && this . isCopyable ( url ) && ! isVideo && [
2020-08-14 14:37:10 +02:00
BDFDB . ReactUtils . createElement ( "span" , {
className : BDFDB . disCN . downloadlink ,
children : "|" ,
style : { margin : "0 5px" }
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Anchor , {
className : BDFDB . disCN . downloadlink ,
2020-08-14 14:51:15 +02:00
children : this . labels . context _copyimage _text ,
2020-08-14 14:37:10 +02:00
onClick : event => {
BDFDB . ListenerUtils . stopEvent ( event ) ;
2020-08-20 14:20:57 +02:00
this . copyImage ( url ) ;
2020-08-14 14:37:10 +02:00
}
} )
] ,
2020-08-20 14:20:57 +02:00
settings . enableZoom && ! isVideo && [
2020-08-14 14:37:10 +02:00
BDFDB . ReactUtils . createElement ( "span" , {
className : BDFDB . disCN . downloadlink ,
children : "|" ,
style : { margin : "0 5px" }
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Anchor , {
className : BDFDB . disCN . downloadlink ,
children : ` Zoom ${ BDFDB . LanguageUtils . LanguageStrings . SETTINGS } ` ,
onClick : openContext ,
onContextMenu : openContext
} )
]
] . flat ( 10 ) . filter ( n => n )
} ) ;
}
2020-08-14 15:43:08 +02:00
let imageIndex = 0 , amount = 1 ;
2020-08-14 14:37:10 +02:00
if ( messages . length ) {
let images = messages . map ( n => Array . from ( n . querySelectorAll ( BDFDB . dotCNS . imagewrapper + "img" ) ) ) . flat ( ) . filter ( img => ! BDFDB . DOMUtils . getParent ( BDFDB . dotCN . spoilerhidden , img ) ) ;
2020-08-14 15:43:08 +02:00
amount = images . length ;
let next , previous ;
2020-08-20 14:20:57 +02:00
for ( let i = 0 ; i < amount ; i ++ ) if ( this . isSameImage ( url , images [ i ] ) ) {
2020-08-14 15:41:54 +02:00
imageIndex = i ;
2020-08-14 14:37:10 +02:00
previous = images [ i - 1 ] ;
next = images [ i + 1 ] ;
break ;
}
if ( previous ) {
if ( e . instance . previousRef ) e . returnvalue . props . children . push ( this . createImageWrapper ( e . instance , e . instance . previousRef , "previous" , BDFDB . LibraryComponents . SvgIcon . Names . LEFT _CARET ) ) ;
else this . loadImage ( e . instance , previous , "previous" ) ;
}
if ( next ) {
if ( e . instance . nextRef ) e . returnvalue . props . children . splice ( 1 , 0 , this . createImageWrapper ( e . instance , e . instance . nextRef , "next" , BDFDB . LibraryComponents . SvgIcon . Names . RIGHT _CARET ) ) ;
else this . loadImage ( e . instance , next , "next" ) ;
}
}
2020-08-14 15:41:21 +02:00
if ( settings . addDetails ) e . returnvalue . props . children . push ( BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _imageutilitiesdetailswrapper ,
children : [
{ label : "Source" , text : e . instance . props . src } ,
{ label : "Size" , text : ` ${ e . instance . props . width } x ${ e . instance . props . height } px ` } ,
2020-08-14 15:41:54 +02:00
{ label : "Image" , text : ` ${ imageIndex + 1 } of ${ amount } ` }
2020-08-14 15:41:21 +02:00
] . map ( data => BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
className : BDFDB . disCN . _imageutilitiesdetails ,
children : [
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _imageutilitiesdetailslabel ,
children : data . label + ":"
} ) ,
data . text
]
} ) )
} ) ) ;
2020-08-14 14:37:10 +02:00
}
if ( e . node ) {
let modal = BDFDB . DOMUtils . getParent ( BDFDB . dotCNC . modal + BDFDB . dotCN . layermodal , e . node ) ;
if ( modal ) {
2020-08-14 21:59:05 +02:00
modal . className = BDFDB . DOMUtils . formatClassName ( modal . className , messages . length && BDFDB . disCN . _imageutilitiesgallery , settings . addDetails && BDFDB . disCN . _imageutilitiesdetailsadded ) ;
2020-08-15 10:38:15 +02:00
this . cleanupListeners ( "Gallery" ) ;
2020-08-14 14:37:10 +02:00
if ( messages . length ) {
2020-08-15 10:38:15 +02:00
document . keydownImageUtilitiesGalleryListener = event => {
if ( ! document . contains ( e . node ) ) this . cleanupListeners ( "Gallery" ) ;
else if ( ! firedEvents . includes ( "Gallery" ) ) {
firedEvents . push ( "Gallery" ) ;
2020-08-14 14:37:10 +02:00
if ( event . keyCode == 37 ) this . switchImages ( e . instance , "previous" ) ;
else if ( event . keyCode == 39 ) this . switchImages ( e . instance , "next" ) ;
}
} ;
2020-08-15 10:38:15 +02:00
document . keyupImageUtilitiesGalleryListener = _ => {
BDFDB . ArrayUtils . remove ( firedEvents , "Gallery" , true ) ;
if ( ! document . contains ( e . node ) ) this . cleanupListeners ( "Gallery" ) ;
2020-08-14 14:37:10 +02:00
} ;
2020-08-15 10:38:15 +02:00
document . addEventListener ( "keydown" , document . keydownImageUtilitiesGalleryListener ) ;
document . addEventListener ( "keyup" , document . keyupImageUtilitiesGalleryListener ) ;
2020-08-14 14:37:10 +02:00
}
}
}
}
processLazyImage ( e ) {
2020-08-14 15:26:54 +02:00
if ( e . node ) {
2020-08-20 14:20:57 +02:00
if ( settings . enableZoom && ! e . node . querySelector ( "video" ) && ! BDFDB . DOMUtils . containsClass ( e . node . parentElement , BDFDB . disCN . _imageutilitiessibling ) && BDFDB . ReactUtils . findOwner ( BDFDB . DOMUtils . getParent ( BDFDB . dotCNC . modal + BDFDB . dotCN . layermodal , e . node ) , { name : "ImageModal" } ) ) {
2020-08-14 15:26:54 +02:00
e . node . addEventListener ( "mousedown" , event => {
2020-08-16 08:21:15 +02:00
if ( event . which != 1 ) return ;
2020-08-14 15:26:54 +02:00
BDFDB . ListenerUtils . stopEvent ( event ) ;
2020-08-14 14:37:10 +02:00
2020-08-14 15:26:54 +02:00
let imgRects = BDFDB . DOMUtils . getRects ( e . node . firstElementChild ) ;
2020-08-14 14:37:10 +02:00
2020-08-15 10:38:15 +02:00
let lense = BDFDB . DOMUtils . create ( ` <div class=" ${ BDFDB . disCN . _imageutilitieslense } " style="border-radius: 50% !important; pointer-events: none !important; z-index: 10000 !important; width: ${ zoomSettings . lensesize } px !important; height: ${ zoomSettings . lensesize } px !important; position: fixed !important;"><div style="position: absolute !important; top: 0 !important; right: 0 !important; bottom: 0 !important; left: 0 !important;">< ${ e . node . firstElementChild . tagName } src=" ${ e . instance . props . src } " style="width: ${ imgRects . width * zoomSettings . zoomlevel } px; height: ${ imgRects . height * zoomSettings . zoomlevel } px; position: fixed !important;" ${ e . node . firstElementChild . tagName == "VIDEO" ? " loop autoplay" : "" } ></ ${ e . node . firstElementChild . tagName } ></div></div> ` ) ;
2020-08-14 15:26:54 +02:00
let pane = lense . firstElementChild . firstElementChild ;
let backdrop = BDFDB . DOMUtils . create ( ` <div class=" ${ BDFDB . disCN . _imageutilitieslensebackdrop } " style="background: rgba(0, 0, 0, 0.3) !important; position: absolute !important; top: 0 !important; right: 0 !important; bottom: 0 !important; left: 0 !important; pointer-events: none !important; z-index: 8000 !important;"></div> ` ) ;
let appMount = document . querySelector ( BDFDB . dotCN . appmount ) ;
appMount . appendChild ( lense ) ;
appMount . appendChild ( backdrop ) ;
2020-08-14 14:37:10 +02:00
2020-08-14 15:26:54 +02:00
let lenseRects = BDFDB . DOMUtils . getRects ( lense ) ;
let halfW = lenseRects . width / 2 , halfH = lenseRects . height / 2 ;
let minX = imgRects . left , maxX = minX + imgRects . width ;
let minY = imgRects . top , maxY = minY + imgRects . height ;
2020-08-15 10:38:15 +02:00
lense . update = _ => {
let x = event . clientX > maxX ? maxX - halfW : event . clientX < minX ? minX - halfW : event . clientX - halfW ;
let y = event . clientY > maxY ? maxY - halfH : event . clientY < minY ? minY - halfH : event . clientY - halfH ;
2020-08-14 15:26:54 +02:00
lense . style . setProperty ( "left" , x + "px" , "important" ) ;
lense . style . setProperty ( "top" , y + "px" , "important" ) ;
2020-08-15 10:38:15 +02:00
lense . style . setProperty ( "width" , zoomSettings . lensesize + "px" , "important" ) ;
lense . style . setProperty ( "height" , zoomSettings . lensesize + "px" , "important" ) ;
lense . style . setProperty ( "clip-path" , ` circle( ${ ( zoomSettings . lensesize / 2 ) + 2 } px at center) ` , "important" ) ;
lense . firstElementChild . style . setProperty ( "clip-path" , ` circle( ${ zoomSettings . lensesize / 2 } px at center) ` , "important" ) ;
2020-08-14 15:26:54 +02:00
pane . style . setProperty ( "left" , imgRects . left + ( ( zoomSettings . zoomlevel - 1 ) * ( imgRects . left - x - halfW ) ) + "px" , "important" ) ;
pane . style . setProperty ( "top" , imgRects . top + ( ( zoomSettings . zoomlevel - 1 ) * ( imgRects . top - y - halfH ) ) + "px" , "important" ) ;
2020-08-15 10:38:15 +02:00
pane . style . setProperty ( "width" , imgRects . width * zoomSettings . zoomlevel + "px" , "important" ) ;
pane . style . setProperty ( "height" , imgRects . height * zoomSettings . zoomlevel + "px" , "important" ) ;
} ;
lense . update ( ) ;
let dragging = event2 => {
event = event2 ;
lense . update ( ) ;
2020-08-14 15:26:54 +02:00
} ;
let releasing = _ => {
2020-08-15 10:38:15 +02:00
this . cleanupListeners ( "Zoom" ) ;
2020-08-14 15:26:54 +02:00
document . removeEventListener ( "mousemove" , dragging ) ;
document . removeEventListener ( "mouseup" , releasing ) ;
BDFDB . DOMUtils . remove ( lense , backdrop ) ;
2020-08-15 10:38:15 +02:00
BDFDB . DataUtils . save ( zoomSettings , this , "zoomSettings" ) ;
2020-08-14 15:26:54 +02:00
} ;
document . addEventListener ( "mousemove" , dragging ) ;
document . addEventListener ( "mouseup" , releasing ) ;
2020-08-15 10:38:15 +02:00
this . cleanupListeners ( "Zoom" ) ;
document . wheelImageUtilitiesZoomListener = event2 => {
if ( ! document . contains ( e . node ) ) this . cleanupListeners ( "Zoom" ) ;
else {
if ( event2 . deltaY < 0 && ( zoomSettings . zoomlevel + 0.1 ) <= this . defaults . zoomSettings . zoomlevel . maxValue ) {
zoomSettings . zoomlevel += 0.1 ;
lense . update ( ) ;
}
else if ( event2 . deltaY > 0 && ( zoomSettings . zoomlevel - 0.1 ) >= this . defaults . zoomSettings . zoomlevel . minValue ) {
zoomSettings . zoomlevel -= 0.1 ;
lense . update ( ) ;
}
}
} ;
document . keydownImageUtilitiesZoomListener = event2 => {
if ( ! document . contains ( e . node ) ) this . cleanupListeners ( "Zoom" ) ;
else if ( ! firedEvents . includes ( "Zoom" ) ) {
firedEvents . push ( "Zoom" ) ;
if ( event2 . keyCode == 187 && ( zoomSettings . zoomlevel + 0.5 ) <= this . defaults . zoomSettings . zoomlevel . maxValue ) {
zoomSettings . zoomlevel += 0.5 ;
lense . update ( ) ;
}
else if ( event2 . keyCode == 189 && ( zoomSettings . zoomlevel - 0.5 ) >= this . defaults . zoomSettings . zoomlevel . minValue ) {
zoomSettings . zoomlevel -= 0.5 ;
lense . update ( ) ;
}
}
} ;
document . keyupImageUtilitiesZoomListener = _ => {
BDFDB . ArrayUtils . remove ( firedEvents , "Zoom" , true ) ;
if ( ! document . contains ( e . node ) ) this . cleanupListeners ( "Zoom" ) ;
} ;
document . addEventListener ( "wheel" , document . wheelImageUtilitiesZoomListener ) ;
document . addEventListener ( "keydown" , document . keydownImageUtilitiesZoomListener ) ;
document . addEventListener ( "keyup" , document . keyupImageUtilitiesZoomListener ) ;
2020-08-14 15:26:54 +02:00
} ) ;
}
}
else if ( e . returnvalue ) {
if ( settings . showOnHover && e . instance . props . original && e . instance . props . src . indexOf ( "https://media.discordapp.net/attachments" ) == 0 && typeof e . returnvalue . props . children == "function" ) {
let attachment = BDFDB . ReactUtils . findValue ( e . instance , "attachment" , { up : true } ) ;
if ( attachment ) {
let renderChildren = e . returnvalue . props . children ;
e . returnvalue . props . children = ( ... args ) => {
return BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TooltipContainer , {
text : ` ${ attachment . filename } \n ${ BDFDB . NumberUtils . formatBytes ( attachment . size ) } \n ${ attachment . width } x ${ attachment . height } px ` ,
tooltipConfig : {
type : "right" ,
delay : amounts . hoverDelay
} ,
children : renderChildren ( ... args )
} ) ;
} ;
}
}
}
}
injectImageDetails ( props , child ) {
2020-08-20 14:20:57 +02:00
if ( settings . showAsHeader ) {
2020-08-14 15:26:54 +02:00
props . detailsAdded = true ;
return BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . embedwrapper ,
children : [
BDFDB . ReactUtils . createElement ( ImageDetails , {
original : props . original ,
attachment : {
height : 0 ,
width : 0 ,
filename : "unknown.png"
}
} ) ,
child
]
2020-08-14 14:37:10 +02:00
} ) ;
}
2020-08-14 15:26:54 +02:00
return child ;
2020-08-14 14:37:10 +02:00
}
2020-08-20 14:20:57 +02:00
isValidImg ( url ) {
const file = url && ( BDFDB . LibraryModules . URLParser . parse ( url ) . pathname || "" ) . toLowerCase ( ) ;
return file && ( file . endsWith ( ".jpg" ) || file . endsWith ( ".jpeg" ) || file . endsWith ( ".png" ) || file . endsWith ( ".gif" ) || file . endsWith ( ".apng" ) || file . endsWith ( ".webp" ) || file . endsWith ( ".svg" ) ) ;
}
isCopyable ( url ) {
const file = url && ( BDFDB . LibraryModules . URLParser . parse ( url ) . pathname || "" ) . toLowerCase ( ) ;
return file . endsWith ( ".jpg" ) || file . endsWith ( ".jpeg" ) || file . endsWith ( ".png" ) ;
}
isSearchable ( url ) {
const file = url && ( BDFDB . LibraryModules . URLParser . parse ( url ) . pathname || "" ) . toLowerCase ( ) ;
return file && ( file . endsWith ( ".jpg" ) || file . endsWith ( ".jpeg" ) || file . endsWith ( ".png" ) || file . endsWith ( ".gif" ) || file . endsWith ( ".apng" ) || file . endsWith ( ".webp" ) ) ;
}
2020-08-14 14:37:10 +02:00
copyImage ( src ) {
BDFDB . LibraryRequires . request ( src , { encoding : null } , ( error , response , buffer ) => {
if ( error ) BDFDB . NotificationUtils . toast ( this . labels . toast _copyimage _failed , { type : "error" } ) ;
else if ( buffer ) {
if ( BDFDB . LibraryRequires . process . platform === "win32" || BDFDB . LibraryRequires . process . platform === "darwin" ) {
BDFDB . LibraryRequires . electron . clipboard . write ( { image : BDFDB . LibraryRequires . electron . nativeImage . createFromBuffer ( buffer ) } ) ;
}
else {
let file = BDFDB . LibraryRequires . path . join ( BDFDB . LibraryRequires . process . env . HOME , "imageutilstempimg.png" ) ;
BDFDB . LibraryRequires . fs . writeFileSync ( file , buffer , { encoding : null } ) ;
BDFDB . LibraryRequires . electron . clipboard . write ( { image : file } ) ;
BDFDB . LibraryRequires . fs . unlinkSync ( file ) ;
}
BDFDB . NotificationUtils . toast ( this . labels . toast _copyimage _success , { type : "success" } ) ;
}
} ) ;
}
getDownloadLocation ( ) {
if ( BDFDB . LibraryRequires . fs . existsSync ( inputs . downloadLocation ) ) return inputs . downloadLocation ;
2020-08-15 09:39:54 +02:00
let homePath = BDFDB . LibraryRequires . process . env . USERPROFILE || BDFDB . LibraryRequires . process . env . HOMEPATH || BDFDB . LibraryRequires . process . env . HOME ;
let downloadPath = homePath && BDFDB . LibraryRequires . path . join ( homePath , "Downloads" ) ;
2020-08-14 20:10:13 +02:00
if ( downloadPath && BDFDB . LibraryRequires . fs . existsSync ( downloadPath ) ) return downloadPath ;
2020-08-14 14:37:10 +02:00
return BDFDB . BDUtils . getPluginsFolder ( ) ;
}
getFileName ( path , fileName , extension , i ) {
let wholePath = BDFDB . LibraryRequires . path . join ( path , i ? ` ${ fileName } ( ${ i } ). ${ extension } ` : ` ${ fileName } . ${ extension } ` ) ;
if ( BDFDB . LibraryRequires . fs . existsSync ( wholePath ) ) return this . getFileName ( path , fileName , extension , i + 1 ) ;
else return wholePath ;
}
getMessageGroupOfImage ( src ) {
2020-08-14 20:10:13 +02:00
if ( src && settings . enableGallery ) for ( let message of document . querySelectorAll ( BDFDB . dotCN . message ) ) for ( let img of message . querySelectorAll ( BDFDB . dotCNS . imagewrapper + "img" ) ) if ( this . isSameImage ( src , img ) ) {
2020-08-14 14:37:10 +02:00
let previousSiblings = [ ] , nextSiblings = [ ] ;
let previousSibling = message . previousSibling , nextSibling = message . nextSibling ;
if ( ! BDFDB . DOMUtils . containsClass ( message , BDFDB . disCN . messagegroupstart ) ) while ( previousSibling ) {
previousSiblings . push ( previousSibling ) ;
if ( BDFDB . DOMUtils . containsClass ( previousSibling , BDFDB . disCN . messagegroupstart ) ) previousSibling = null ;
else previousSibling = previousSibling . previousSibling ;
}
while ( nextSibling ) {
if ( ! BDFDB . DOMUtils . containsClass ( nextSibling , BDFDB . disCN . messagegroupstart ) ) {
nextSiblings . push ( nextSibling ) ;
nextSibling = nextSibling . nextSibling ;
}
else nextSibling = null ;
}
return [ ] . concat ( previousSiblings . reverse ( ) , message , nextSiblings ) . filter ( n => n && BDFDB . DOMUtils . containsClass ( n , BDFDB . disCN . message ) ) ;
}
return [ ] ;
}
isSameImage ( src , img ) {
return img . src && ( Node . prototype . isPrototypeOf ( src ) && img == src || ! Node . prototype . isPrototypeOf ( src ) && this . getImageSrc ( img ) == this . getImageSrc ( src ) ) ;
}
getImageSrc ( img ) {
if ( ! img ) return null ;
return ( typeof img == "string" ? img : ( img . src || ( img . querySelector ( "canvas" ) ? img . querySelector ( "canvas" ) . src : "" ) ) ) . split ( "?width=" ) [ 0 ] ;
}
createImageWrapper ( instance , imgRef , type , svgIcon ) {
return BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCNS . _imageutilitiessibling + BDFDB . disCN [ ` _imageutilities ${ type } ` ] ,
onClick : _ => { this . switchImages ( instance , type ) ; } ,
children : [
imgRef ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . SvgIcon , {
2020-08-16 08:21:15 +02:00
className : BDFDB . disCNS . _imageutilitiesswitchicon + BDFDB . disCN . svgicon ,
2020-08-14 14:37:10 +02:00
name : svgIcon
} )
]
} ) ;
}
loadImage ( instance , img , type ) {
let imageThrowaway = document . createElement ( "img" ) ;
let src = this . getImageSrc ( img ) ;
imageThrowaway . src = src ;
imageThrowaway . onload = _ => {
let arects = BDFDB . DOMUtils . getRects ( document . querySelector ( BDFDB . dotCN . appmount ) ) ;
let resizeY = ( arects . height / imageThrowaway . naturalHeight ) * 0.65 , resizeX = ( arects . width / imageThrowaway . naturalWidth ) * 0.8 ;
let resize = resizeX < resizeY ? resizeX : resizeY ;
let newHeight = imageThrowaway . naturalHeight * resize ;
let newWidth = imageThrowaway . naturalWidth * resize ;
instance [ type + "Img" ] = img ;
instance [ type + "Ref" ] = BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . LazyImage , {
src : src ,
height : imageThrowaway . naturalHeight ,
width : imageThrowaway . naturalWidth ,
maxHeight : newHeight ,
maxWidth : newWidth ,
} ) ;
BDFDB . ReactUtils . forceUpdate ( instance ) ;
} ;
}
switchImages ( instance , type ) {
let img = instance [ type + "Img" ] ;
let imgRef = instance [ type + "Ref" ] ;
if ( ! img || ! imgRef ) return ;
delete instance . previousRef ;
delete instance . nextRef ;
delete instance . previousImg ;
delete instance . nextImg ;
instance . props . original = imgRef . props . src ;
instance . props . placeholder = imgRef . props . src ;
instance . props . src = imgRef . props . src ;
instance . props . height = imgRef . props . height ;
instance . props . width = imgRef . props . width ;
instance . props . cachedImage = img ;
BDFDB . ReactUtils . forceUpdate ( instance ) ;
}
2020-08-15 10:38:15 +02:00
cleanupListeners ( type ) {
if ( ! type ) return ;
for ( let eventType of [ "wheel" , "keydown" , "keyup" ] ) {
document . removeEventListener ( "wheel" , document [ ` ${ eventType } ImageUtilities ${ type } Listener ` ] ) ;
delete document [ ` ${ eventType } ImageUtilities ${ type } Listener ` ] ;
}
2020-08-14 14:37:10 +02:00
}
forceUpdateAll ( ) {
settings = BDFDB . DataUtils . get ( this , "settings" ) ;
2020-08-14 15:26:54 +02:00
amounts = BDFDB . DataUtils . get ( this , "amounts" ) ;
2020-08-14 14:37:10 +02:00
inputs = BDFDB . DataUtils . get ( this , "inputs" ) ;
zoomSettings = BDFDB . DataUtils . get ( this , "zoomSettings" ) ;
engines = BDFDB . DataUtils . get ( this , "engines" ) ;
enabledEngines = BDFDB . ObjectUtils . filter ( engines , n => n ) ;
BDFDB . ModuleUtils . forceAllUpdates ( this ) ;
2020-08-14 15:41:21 +02:00
BDFDB . MessageUtils . rerenderAll ( ) ;
2020-08-14 14:37:10 +02:00
}
setLabelsByLanguage ( ) {
switch ( BDFDB . LanguageUtils . getLanguage ( ) . id ) {
case "hr" : //croatian
return {
toast _copyimage _success : "Kopirana je slika u međuspremnik" ,
toast _copyimage _failed : "Kopiranje slike u međuspremnik nije uspjelo" ,
toast _copyimagelink _success : "Kopirana slika povezana na međuspremnik" ,
toast _saveimage _success : "Slika je spremljena u '{{path}}'" ,
toast _saveimage _failed : "Spremanje slike na '{{path}}' nije uspjelo" ,
context _viewimage _text : "Pogledati sliku" ,
context _saveimage _text : "Preuzmite sliku" ,
context _copyimage _text : "Kopiraj sliku" ,
context _copyimagelink _text : "Kopirajte vezu slike" ,
context _reverseimagesearch _text : "Traži sliku ..." ,
context _lensesize _text : "Veličina leće" ,
submenu _disabled _text : "Svi su onemogućeni"
} ;
case "da" : //danish
return {
toast _copyimage _success : "Kopieret billede til udklipsholder" ,
toast _copyimage _failed : "Kunne ikke kopiere billedet til udklipsholderen" ,
toast _copyimagelink _success : "Kopieret billedlink til udklipsholder" ,
toast _saveimage _success : "Billedet er gemt i '{{path}}'" ,
toast _saveimage _failed : "Kunne ikke gemme billedet i '{{path}}'" ,
context _viewimage _text : "Se billede" ,
context _saveimage _text : "Download billede" ,
context _copyimage _text : "Kopier billede" ,
context _copyimagelink _text : "Kopier billedlink" ,
context _reverseimagesearch _text : "Søg billede med ..." ,
context _lensesize _text : "Linsestørrelse" ,
submenu _disabled _text : "Alle deaktiveret"
} ;
case "de" : //german
return {
toast _copyimage _success : "Bild in Zwischenablage kopiert" ,
toast _copyimage _failed : "Bild konnte nicht in die Zwischenablage kopiert werden" ,
toast _copyimagelink _success : "Bildlink in Zwischenablage kopiert" ,
toast _saveimage _success : "Bild wurde in '{{path}}' gespeichert" ,
toast _saveimage _failed : "Bild konnte nicht in '{{path}}' gespeichert werden" ,
context _viewimage _text : "Bild ansehen" ,
context _saveimage _text : "Bild herunterladen" ,
context _copyimage _text : "Bild kopieren" ,
context _copyimagelink _text : "Bildlink kopieren" ,
context _reverseimagesearch _text : "Bild suchen mit ..." ,
context _lensesize _text : "Linsengröße" ,
submenu _disabled _text : "Alle deaktiviert"
} ;
case "es" : //spanish
return {
toast _copyimage _success : "Imagen copiada al portapapeles" ,
toast _copyimage _failed : "No se pudo copiar la imagen al portapapeles" ,
toast _copyimagelink _success : "Enlace de imagen copiado al portapapeles" ,
toast _saveimage _success : "Imagen guardada en '{{path}}'" ,
toast _saveimage _failed : "No se pudo guardar la imagen en '{{path}}'" ,
context _viewimage _text : "Ver imagen" ,
context _saveimage _text : "Descargar imagen" ,
context _copyimage _text : "Copiar imagen" ,
context _copyimagelink _text : "Copiar enlace de imagen" ,
context _reverseimagesearch _text : "Buscar imagen con ..." ,
context _lensesize _text : "Tamaño de la lente" ,
submenu _disabled _text : "Todo desactivado"
} ;
case "fr" : //french
return {
toast _copyimage _success : "Image copiée dans le presse-papiers" ,
toast _copyimage _failed : "Échec de la copie de l'image dans le presse-papiers" ,
toast _copyimagelink _success : "Lien d'image copié dans le presse-papiers" ,
toast _saveimage _success : "Image enregistrée dans '{{path}}'" ,
toast _saveimage _failed : "Échec de l'enregistrement de l'image dans '{{path}}'" ,
context _viewimage _text : "Voir l'image" ,
context _saveimage _text : "Télécharger l'image" ,
context _copyimage _text : "Copier l'image" ,
context _copyimagelink _text : "Copier le lien de l'image" ,
context _reverseimagesearch _text : "Rechercher une image avec ..." ,
context _lensesize _text : "Taille de la lentille" ,
submenu _disabled _text : "Tous désactivés"
} ;
case "it" : //italian
return {
toast _copyimage _success : "Immagine copiata negli appunti" ,
toast _copyimage _failed : "Impossibile copiare l'immagine negli appunti" ,
toast _copyimagelink _success : "Collegamento dell'immagine copiato negli appunti" ,
toast _saveimage _success : "Immagine salvata in '{{path}}'" ,
toast _saveimage _failed : "Impossibile salvare l'immagine in '{{path}}'" ,
context _viewimage _text : "Guarda l'immagine" ,
context _saveimage _text : "Scarica immagine" ,
context _copyimage _text : "Copia l'immagine" ,
context _copyimagelink _text : "Copia link immagine" ,
context _reverseimagesearch _text : "Cerca immagine con ..." ,
context _lensesize _text : "Dimensione dell'obiettivo" ,
submenu _disabled _text : "Tutto disattivato"
} ;
case "nl" : //dutch
return {
toast _copyimage _success : "Gekopieerde afbeelding naar klembord" ,
toast _copyimage _failed : "Kan afbeelding niet naar klembord kopiëren" ,
toast _copyimagelink _success : "Gekopieerde afbeeldingslink naar klembord" ,
toast _saveimage _success : "Afbeelding opgeslagen in '{{path}}'" ,
toast _saveimage _failed : "Kan afbeelding niet opslaan in '{{path}}'" ,
context _viewimage _text : "Bekijk afbeelding" ,
context _saveimage _text : "Download afbeelding" ,
context _copyimage _text : "Kopieer afbeelding" ,
context _copyimagelink _text : "Kopieer afbeeldingslink" ,
context _reverseimagesearch _text : "Afbeelding zoeken met ..." ,
context _lensesize _text : "Lensgrootte" ,
submenu _disabled _text : "Alles gedeactiveerd"
} ;
case "no" : //norwegian
return {
toast _copyimage _success : "Kopiert bilde til utklippstavlen" ,
toast _copyimage _failed : "Kunne ikke kopiere bildet til utklippstavlen" ,
toast _copyimagelink _success : "Kopiert bildelink til utklippstavlen" ,
toast _saveimage _success : "Bilde lagret i '{{path}}'" ,
toast _saveimage _failed : "Kunne ikke lagre bildet i '{{path}}'" ,
context _viewimage _text : "Vis bilde" ,
context _saveimage _text : "Last ned bilde" ,
context _copyimage _text : "Kopier bilde" ,
context _copyimagelink _text : "Kopier bildelink" ,
context _reverseimagesearch _text : "Søk på bilde med ..." ,
context _lensesize _text : "Linsestørrelse" ,
submenu _disabled _text : "Alle deaktivert"
} ;
case "pl" : //polish
return {
toast _copyimage _success : "Skopiowany obraz do schowka" ,
toast _copyimage _failed : "Nie udało się skopiować obrazu do schowka" ,
toast _copyimagelink _success : "Link do skopiowanego obrazu do schowka" ,
toast _saveimage _success : "Obraz zapisany w '{{path}}'" ,
toast _saveimage _failed : "Nie udało się zapisać obrazu w '{{path}}'" ,
context _viewimage _text : "Zobacz obraz" ,
context _saveimage _text : "Pobierz obraz" ,
context _copyimage _text : "Skopiuj obraz" ,
context _copyimagelink _text : "Kopiuj łącze do obrazu" ,
context _reverseimagesearch _text : "Wyszukaj obraz za pomocą ..." ,
context _lensesize _text : "Rozmiar obiektywu" ,
submenu _disabled _text : "Wszystkie wyłączone"
} ;
case "pt-BR" : //portuguese (brazil)
return {
toast _copyimage _success : "Imagem copiada para a área de transferência" ,
toast _copyimage _failed : "Falha ao copiar imagem para a área de transferência" ,
toast _copyimagelink _success : "Link da imagem copiada para a área de transferência" ,
toast _saveimage _success : "Imagem salva em '{{path}}'" ,
toast _saveimage _failed : "Falha ao salvar imagem em '{{path}}'" ,
context _viewimage _text : "Ver imagem" ,
context _saveimage _text : "Baixar imagem" ,
context _copyimage _text : "Copiar imagem" ,
context _copyimagelink _text : "Copiar link da imagem" ,
context _reverseimagesearch _text : "Pesquisar imagem com ..." ,
context _lensesize _text : "Tamanho da lente" ,
submenu _disabled _text : "Todos desativados"
} ;
case "fi" : //finnish
return {
toast _copyimage _success : "Kopioitu kuva leikepöydälle" ,
toast _copyimage _failed : "Kuvan kopiointi leikepöydälle epäonnistui" ,
toast _copyimagelink _success : "Kopioitu kuvan linkki leikepöydälle" ,
toast _saveimage _success : "Kuva tallennettu '{{path}}'" ,
toast _saveimage _failed : "Kuvan tallentaminen epäonnistui '{{path}}'" ,
context _viewimage _text : "Näytä kuva" ,
context _saveimage _text : "Lataa kuva" ,
context _copyimage _text : "Kopioi kuva" ,
context _copyimagelink _text : "Kopioi kuvan linkki" ,
context _reverseimagesearch _text : "Hae kuvaa ..." ,
context _lensesize _text : "Linssin koko" ,
submenu _disabled _text : "Kaikki on poistettu käytöstä"
} ;
case "sv" : //swedish
return {
toast _copyimage _success : "Kopierad bild till urklipp" ,
toast _copyimage _failed : "Det gick inte att kopiera bilden till urklipp" ,
toast _copyimagelink _success : "Kopierad bildlänk till urklipp" ,
toast _saveimage _success : "Bild sparad i '{{path}}'" ,
toast _saveimage _failed : "Det gick inte att spara bilden i '{{path}}'" ,
context _viewimage _text : "Se bild" ,
context _saveimage _text : "Ladda ner bild" ,
context _copyimage _text : "Kopiera bild" ,
context _copyimagelink _text : "Kopiera bildlänk" ,
context _reverseimagesearch _text : "Sök bild med ..." ,
context _lensesize _text : "Linsstorlek" ,
submenu _disabled _text : "Alla avaktiverade"
} ;
case "tr" : //turkish
return {
toast _copyimage _success : "Görüntü panoya kopyalandı " ,
toast _copyimage _failed : "Görüntü panoya kopyalanamadı " ,
toast _copyimagelink _success : "Görsel bağlantı sı panoya kopyalandı " ,
toast _saveimage _success : "Resim '{{path}}' konumuna kaydedildi" ,
toast _saveimage _failed : "'{{path}}' konumuna resim kaydedilemedi" ,
context _viewimage _text : "Resmi görüntüle" ,
context _saveimage _text : "Resmi İndir" ,
context _copyimage _text : "Resmi kopyala" ,
context _copyimagelink _text : "Görüntü Bağlantı sı nı kopyala" ,
context _reverseimagesearch _text : "Görüntüyü şununla ara ..." ,
context _lensesize _text : "Lens boyutu" ,
submenu _disabled _text : "Hepsi deaktive"
} ;
case "cs" : //czech
return {
toast _copyimage _success : "Zkopírován obrázek do schránky" ,
toast _copyimage _failed : "Nepodařilo se kopírovat obrázek do schránky" ,
toast _copyimagelink _success : "Odkaz na zkopírovaný obrázek do schránky" ,
toast _saveimage _success : "Obrázek uložený v '{{path}}'" ,
toast _saveimage _failed : "Nepodařilo se uložit obrázek do '{{path}}'" ,
context _viewimage _text : "Zobrazit obrázek" ,
context _saveimage _text : "Stáhnout obrázek" ,
context _copyimage _text : "Kopírovat obrázek" ,
context _copyimagelink _text : "Kopírovat odkaz na obrázek" ,
context _reverseimagesearch _text : "Vyhledat obrázek pomocí ..." ,
context _lensesize _text : "Velikost objektivu" ,
submenu _disabled _text : "Všechny deaktivované"
} ;
case "bg" : //bulgarian
return {
toast _copyimage _success : "Копирано изображение в клипборда" ,
toast _copyimage _failed : "Копирането на изображение в буферната памет не б е успешно" ,
toast _copyimagelink _success : "Копирано изображение за връзка в клипборда" ,
toast _saveimage _success : "Изображението е запазено в '{{path}}'" ,
toast _saveimage _failed : "Неуспешно запазване на изображението в '{{path}}'" ,
context _viewimage _text : "Вижте изображението" ,
context _saveimage _text : "Изтегляне на изображението" ,
context _copyimage _text : "Копирай изображение" ,
context _copyimagelink _text : "Копиране на изображението" ,
context _reverseimagesearch _text : "Търсене на изображение с ..." ,
context _lensesize _text : "Размер на обектива" ,
submenu _disabled _text : "Всички с а деактивирани"
} ;
case "ru" : //russian
return {
toast _copyimage _success : "Изображение скопировано в буфер обмена" ,
toast _copyimage _failed : "Н е удалось скопировать изображение в буфер обмена" ,
toast _copyimagelink _success : "Ссылка на скопированное изображение в буфер обмена" ,
toast _saveimage _success : "Изображение сохранено в '{{path}}'" ,
toast _saveimage _failed : "Н е удалось сохранить изображение в '{{path}}'" ,
context _viewimage _text : "Просмотр изображения" ,
context _saveimage _text : "Скачать изображение" ,
context _copyimage _text : "Копировать изображение" ,
context _copyimagelink _text : "Копировать ссылку на изображение" ,
context _reverseimagesearch _text : "Поиск изображения с ..." ,
context _lensesize _text : "Размер объектива" ,
submenu _disabled _text : "В с е деактивированные"
} ;
case "uk" : //ukrainian
return {
toast _copyimage _success : "Скопійоване зображення в буфер обміну" ,
toast _copyimage _failed : "Н е вдалося скопіювати зображення в буфер обміну" ,
toast _copyimagelink _success : "Скопійоване зображення посилання на буфер обміну" ,
toast _saveimage _success : "Зображення збережено на '{{path}}'" ,
toast _saveimage _failed : "Н е вдалося зберегти зображення на '{{path}}'" ,
context _viewimage _text : "Переглянути зображення" ,
context _saveimage _text : "Завантажити зображення" ,
context _copyimage _text : "Скопіювати зображення" ,
context _copyimagelink _text : "Скопіюйте посилання на зображення" ,
context _reverseimagesearch _text : "Шукати зображення за допомогою ..." ,
context _lensesize _text : "Розмір о б 'єктива" ,
submenu _disabled _text : "В с і вимкнені"
} ;
case "ja" : //japanese
return {
toast _copyimage _success : "画像をクリップボードにコピー" ,
toast _copyimage _failed : "画像をクリップボードにコピーできませんでした" ,
toast _copyimagelink _success : "クリップボードへの画像リンクのコピー" ,
toast _saveimage _success : "画像は'{{path}}'に保存されました" ,
toast _saveimage _failed : "画像を'{{path}}'に保存できませんでした" ,
context _viewimage _text : "画像を見る" ,
context _saveimage _text : "画像をダウンロード" ,
context _copyimage _text : "画像をコピー" ,
context _copyimagelink _text : "画像リンクをコピー" ,
context _reverseimagesearch _text : "で画像を検索 ..." ,
context _lensesize _text : "レンズサイズ" ,
submenu _disabled _text : "すべて非アクティブ化"
} ;
case "zh-TW" : //chinese (traditional)
return {
toast _copyimage _success : "複製的圖像到剪貼板" ,
toast _copyimage _failed : "無法將圖像複製到剪貼板" ,
toast _copyimagelink _success : "複製的圖像鏈接到剪貼板" ,
toast _saveimage _success : "圖片保存在'{{path}}'中" ,
toast _saveimage _failed : "無法將圖像保存到'{{path}}'中" ,
context _viewimage _text : "看圖片" ,
context _saveimage _text : "下載圖片" ,
context _copyimage _text : "複製圖片" ,
context _copyimagelink _text : "複製圖像鏈接" ,
context _lensesize _text : "鏡片尺寸" ,
context _reverseimagesearch _text : "搜尋圖片 ..." ,
submenu _disabled _text : "全部停用"
} ;
case "ko" : //korean
return {
toast _copyimage _success : "클립 보드에 복사 된 이미지" ,
toast _copyimage _failed : "이미지를 클립 보드로 복사하지 못했습니다" ,
toast _copyimagelink _success : "클립 보드에 복사 된 이미지 링크" ,
toast _saveimage _success : "'{{path}}'에 저장된 이미지" ,
toast _saveimage _failed : "'{{path}}'에 이미지를 저장하지 못했습니다" ,
context _viewimage _text : "이미지보기" ,
context _saveimage _text : "이미지 다운로드" ,
context _copyimage _text : "복사 이미지" ,
context _copyimagelink _text : "이미지 링크 복사" ,
context _reverseimagesearch _text : "로 이미지 검색 ..." ,
context _lensesize _text : "렌즈 크기" ,
submenu _disabled _text : "모두 비활성화 됨"
} ;
default : //default: english
return {
toast _copyimage _success : "Copied image to clipboard" ,
toast _copyimage _failed : "Failed to copy image to clipboard" ,
toast _copyimagelink _success : "Copied image link to clipboard" ,
toast _saveimage _success : "Saved image in '{{path}}'" ,
toast _saveimage _failed : "Failed to save image in '{{path}}'" ,
context _viewimage _text : "View Image" ,
context _saveimage _text : "Download Image" ,
context _copyimage _text : "Copy Image" ,
context _copyimagelink _text : "Copy Image Link" ,
context _reverseimagesearch _text : "Search Image with ..." ,
context _lensesize _text : "Lense Size" ,
submenu _disabled _text : "All disabled"
} ;
}
}
}
} ) ( ) ;
2020-08-25 00:17:15 +02:00
module . exports = ImageUtilities ;