diff --git a/README.md b/README.md index 693038f..bb51f2c 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ We moved our instances list to our webpage: https://www.halcyon.social/instances or read our new documentation pages to install it manually: https://www.halcyon.social/documentation.php?page=install ## Blog +- Release of Version 2.3.4 - Introduce BlurHash,repair YouPlay,improve link previews feature,add debug mode,add lighttpd example config,bug fixes - Release of Version 2.3.3 - New media uploader,sort uploads,drag&drop and copy&paste uploads,fix automatic dark mode - Release of Version 2.3.2 - Add block and mute management,add management for follow requests,add Catalan translation - Release of Version 2.3.1 - Fix duplicated thread,allow adding more toots as reply chain,add Dutch translation,more bugfixes,improved translations. diff --git a/assets/css/style.css b/assets/css/style.css index f803842..65e596b 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -577,6 +577,9 @@ border-top: 1px solid #E1E8ED; .single_reply_status .status_preview .toot_entry .toot_footer,.report_stauts .status_preview .toot_entry .toot_footer { display: none!important; } +.single_reply_status .status_preview .toot_entry .link_preview,.report_stauts .status_preview .toot_entry .link_preview { +display: none!important; +} .single_reply_status .status_form .status_bottom,.report_status .status_form .status_bottom { width: 100%; margin-left: 0; @@ -993,6 +996,9 @@ position: absolute; width: 100%; height: 100%; background-color: #000; +background-size:cover; +background-position:center; +text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; } .media_views.sensitive .sensitive_alart .text1 { font-size: 26px; diff --git a/assets/js/autocomplete/textarea.js b/assets/js/autocomplete/textarea.js index 6044ed2..541c600 100644 --- a/assets/js/autocomplete/textarea.js +++ b/assets/js/autocomplete/textarea.js @@ -64,6 +64,7 @@ getDropDown().removeClass('showDropDown').addClass('hideDropDown'); if(resultname) { if(resultname == "acct") { if(ele.display_name == "") ele.display_name = ele.username; +ele.display_name = htmlEscape(ele.display_name); for(var i=0;i"); } diff --git a/assets/js/blurhash.js b/assets/js/blurhash.js new file mode 100644 index 0000000..1d2183b --- /dev/null +++ b/assets/js/blurhash.js @@ -0,0 +1,129 @@ +(function($) { +var digitCharacters = [ +"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", +"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", +"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", +"U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", +"e", "f", "g", "h", "i", "j", "k", "l", "m", "n", +"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", +"y", "z", "#", "$", "%", "*", "+", ",", "-", ".", +":", ";", "=", "?", "@", "[", "]", "^", "_", "{", +"|", "}", "~", +]; +function decode83(str) { +var value = 0; +for (var i = 0; i < str.length; i++) { +var c = str[i]; +var digit = digitCharacters.indexOf(c); +value = value * 83 + digit; +} +return value; +} +function sRGBToLinear(value) { +var v = value / 255; +if (v <= 0.04045) { +return v / 12.92; +} +else { +return Math.pow((v + 0.055) / 1.055, 2.4); +} +} +function linearTosRGB(value) { +var v = Math.max(0, Math.min(1, value)); +if (v <= 0.0031308) { +return Math.round(v * 12.92 * 255 + 0.5); +} +else { +return Math.round((1.055 * Math.pow(v, 1 / 2.4) - 0.055) * 255 + 0.5); +} +} +function sign(n) { +return (n < 0 ? -1 : 1); +} +function signPow(val, exp) { +return sign(val) * Math.pow(Math.abs(val), exp); +} +function decodeDC(value) { +var intR = value >> 16; +var intG = (value >> 8) & 255; +var intB = value & 255; +return [sRGBToLinear(intR), sRGBToLinear(intG), sRGBToLinear(intB)]; +} +function decodeAC(value, maximumValue) { +var quantR = Math.floor(value / (19 * 19)); +var quantG = Math.floor(value / 19) % 19; +var quantB = value % 19; +var rgb = [ +signPow((quantR - 9) / 9, 2.0) * maximumValue, +signPow((quantG - 9) / 9, 2.0) * maximumValue, +signPow((quantB - 9) / 9, 2.0) * maximumValue, +]; +return rgb; +} +$.decode = function(blurhash,width,height,punch) { +punch = punch | 1; +if (blurhash.length < 6) { +console.error('too short blurhash'); +return null; +} +var sizeFlag = decode83(blurhash[0]); +var numY = Math.floor(sizeFlag / 9) + 1; +var numX = (sizeFlag % 9) + 1; +var quantisedMaximumValue = decode83(blurhash[1]); +var maximumValue = (quantisedMaximumValue + 1) / 166; +if (blurhash.length !== 4 + 2 * numX * numY) { +console.error('blurhash length mismatch', blurhash.length, 4 + 2 * numX * numY); +return null; +} +var colors = new Array(numX * numY); +for (var i = 0; i < colors.length; i++) { +if (i === 0) { +var value = decode83(blurhash.substring(2, 6)); +colors[i] = decodeDC(value); +} +else { +var value = decode83(blurhash.substring(4 + i * 2, 6 + i * 2)); +colors[i] = decodeAC(value, maximumValue * punch); +} +} +var bytesPerRow = width * 4; +var pixels = new Uint8ClampedArray(bytesPerRow * height); +for (var y = 0; y < height; y++) { +for (var x = 0; x < width; x++) { +var r = 0; +var g = 0; +var b = 0; +for (var j = 0; j < numY; j++) { +for (var i = 0; i < numX; i++) { +var basis = Math.cos(Math.PI * x * i / width) * Math.cos(Math.PI * y * j / height); +var color = colors[i + j * numX]; +r += color[0] * basis; +g += color[1] * basis; +b += color[2] * basis; +} +} +var intR = linearTosRGB(r); +var intG = linearTosRGB(g); +var intB = linearTosRGB(b); +pixels[4 * x + 0 + y * bytesPerRow] = intR; +pixels[4 * x + 1 + y * bytesPerRow] = intG; +pixels[4 * x + 2 + y * bytesPerRow] = intB; +pixels[4 * x + 3 + y * bytesPerRow] = 255; +} +} +return pixels; +} +})(jQuery); +function getBlurImage(hash) { +const pixels = $.decode(hash,32,32); +if(pixels) { +const canvas = document.createElement("canvas"); +canvas.height = 32; +canvas.width = 32; +const ctx = canvas.getContext('2d'); +const imagedata = new ImageData(pixels,32,32); +ctx.putImageData(imagedata,0,0); +return canvas.toDataURL(); +} +else return false; +} diff --git a/assets/js/halcyon/halcyonFunctions.js b/assets/js/halcyon/halcyonFunctions.js index 7b99215..b4a9eea 100644 --- a/assets/js/halcyon/halcyonFunctions.js +++ b/assets/js/halcyon/halcyonFunctions.js @@ -119,71 +119,6 @@ else if(ytbe) embedMedia("youtube",$(this).closest(".toot_article"),ytbe[2]); else if(htbe) embedMedia("youtube",$(this).closest(".toot_article"),htbe[2]); else if(vimeo) embedMedia("vimeo",$(this).closest(".toot_article"),vimeo[2]); else if(peertube) embedMedia("peertube",$(this).closest(".toot_article"),peertube[0].replace("/watch/","/embed/")); -else if(localStorage.setting_link_previews == "true") { -if(!window.cards) { -cards = new Array(); -} -if(!$(this).attr("class") && $(this).parent().parent().parent().parent().parent().attr("sid") != undefined) { -if(!cards[$(this).parent().parent().parent().parent().parent().attr("sid")]) { -var this_id = $(this).parent().parent().parent().parent().parent().attr("sid"); -api.get("statuses/"+$(this).parent().parent().parent().parent().parent().attr("sid")+"/card",function(data) { -cards[this_id] = data; -if($(".toot_entry[sid="+this_id+"]").children().children("section").children("article").children(".link_preview").length == 0 && data.url) { -$(".toot_entry[sid="+this_id+"]").children().children("section").children("article").append( -$("
").addClass("media_views").addClass("link_preview").attr("sid",this_id).attr("media_length",1).css("height","unset").data("url",data.url).append( -$("").attr("src",data.image).width(data.width).css("max-width","200px").css("float","left").css("margin-right","5px")).append( -$("").text(data.title)).append($("
")).append( -$("").text(data.description)).append($("
")).append( -$("").css("color","#777777").text(data.url)).click(function(e) { -e.stopPropagation(); -window.open($(this).data("url"),"_blank"); -}) -); -} -if($(".main_status[sid="+this_id+"]").children().children("section").children("article").children(".link_preview").length == 0 && data.url) { -$(".main_status[sid="+this_id+"]").children().children("section").children("article").append( -$("
").addClass("media_views").addClass("link_preview").attr("sid",this_id).attr("media_length",1).css("height","unset").data("url",data.url).append( -$("").attr("src",data.image).width(data.width).css("max-width","200px").css("float","left").css("margin-right","5px")).append( -$("").text(data.title)).append($("
")).append( -$("").text(data.description)).append($("
")).append( -$("").css("color","#777777").text(data.url)).click(function(e) { -e.stopPropagation(); -window.open($(this).data("url"),"_blank"); -}) -); -} -}); -} -else { -var this_id = $(this).parent().parent().parent().parent().parent().attr("sid"); -data = cards[this_id]; -if($(".toot_entry[sid="+this_id+"]").children().children("section").children("article").children(".link_preview").length == 0 && data.url) { -$(".toot_entry[sid="+this_id+"]").children().children("section").children("article").append( -$("
").addClass("media_views").addClass("link_preview").attr("sid",this_id).attr("media_length",1).css("height","unset").data("url",data.url).append( -$("").attr("src",data.image).width(data.width).css("max-width","200px").css("float","left").css("margin-right","5px")).append( -$("").text(data.title)).append($("
")).append( -$("").text(data.description)).append($("
")).append( -$("").css("color","#777777").text(data.url)).click(function(e) { -e.stopPropagation(); -window.open($(this).data("url"),"_blank"); -}) -); -} -if($(".main_status[sid="+this_id+"]").children().children("section").children("article").children(".link_preview").length == 0 && data.url) { -$(".main_status[sid="+this_id+"]").children().children("section").children("article").append( -$("
").addClass("media_views").addClass("link_preview").attr("sid",this_id).attr("media_length",1).css("height","unset").data("url",data.url).append( -$("").attr("src",data.image).width(data.width).css("max-width","200px").css("float","left").css("margin-right","5px")).append( -$("").text(data.title)).append($("
")).append( -$("").text(data.description)).append($("
")).append( -$("").css("color","#777777").text(data.url)).click(function(e) { -e.stopPropagation(); -window.open($(this).data("url"),"_blank"); -}) -); -} -} -} -} }); } function getConversionedDate(key, value) { diff --git a/assets/js/halcyon/halcyonTemplates.js b/assets/js/halcyon/halcyonTemplates.js index 4f7bf29..96812ff 100644 --- a/assets/js/halcyon/halcyonTemplates.js +++ b/assets/js/halcyon/halcyonTemplates.js @@ -2,6 +2,7 @@ function mediaattachments_template(status) { let media_views = ""; var border = ""; var mvfullheight = ""; +var blurbackground = ""; var dsplength = status.media_attachments.length; if(status.media_attachments[0].remote_url != null) { status.media_attachments[0].url = status.media_attachments[0].remote_url; @@ -18,8 +19,9 @@ else if(!status.sensitive || localStorage.setting_show_nsfw == "true") { media_views = `
`; } else { +if(status.media_attachments[0].blurhash) blurbackground = 'style="background-image:url('+getBlurImage(status.media_attachments[0].blurhash)+')"'; media_views = `
-
+
${__('Sensitive content')} ${__('Click to view')}
`; @@ -82,6 +84,27 @@ media_views += "
"; } return media_views; } +function link_preview_template(card) { +if(localStorage.setting_link_previews == "true") { +const ytcom = card.url.match(/https?:\/\/(www\.)?youtube\.com\/watch\?v=([a-zA-Z\d_-]+)/); +const htcom = card.url.match(/https?:\/\/(www\.)?hooktube\.com\/watch\?v=([a-zA-Z\d_-]+)/); +const ivcom = card.url.match(/https?:\/\/(www\.)?invidio\.us\/watch\?v=([a-zA-Z\d_-]+)/); +const ytbe = card.url.match(/https?:\/\/(www\.)?youtu\.be\/([a-zA-Z\d_-]+)/); +const htbe = card.url.match(/https?:\/\/(www\.)?hooktube\.com\/([a-zA-Z\d_-]+)/); +const vimeo = card.url.match(/https?:\/\/(www\.)?vimeo\.com\/([\d]+)/); +const peertube = card.url.match(/https?:\/\/.+..+\/videos\/watch\/([\da-z]{8}-[\da-z]{4}-[\da-z]{4}-[\da-z]{4}-[\da-z]{12})\/?$/); +if(((!ytcom && !htcom && !ivcom && !ytbe && !htbe) || (localStorage.setting_play_youplay == "false" && localStorage.setting_play_invidious == "false")) && (!vimeo || localStorage.setting_play_vimeo) && (!peertube || localStorage.setting_play_peertube)) { +let preview_html = (`