Browse Source

Merge branch 'main' into fix-comment-edit

pull/30706/head
wxiaoguang 1 week ago
parent
commit
bb9de498fc
No account linked to committer's email address
2 changed files with 110 additions and 110 deletions
  1. 8
    8
      options/locale/locale_pt-PT.ini
  2. 102
    102
      web_src/js/features/imagediff.js

+ 8
- 8
options/locale/locale_pt-PT.ini View File

@@ -2358,7 +2358,7 @@ settings.protected_branch.delete_rule=Eliminar regra
settings.protected_branch_can_push=Permitir envios?
settings.protected_branch_can_push_yes=Pode enviar
settings.protected_branch_can_push_no=Não pode enviar
settings.branch_protection=Salvaguarda do ramo '<b>%s</b>'
settings.branch_protection=Regras de salvaguarda do ramo '<b>%s</b>'
settings.protect_this_branch=Habilitar salvaguarda do ramo
settings.protect_this_branch_desc=Impede a eliminação e restringe envios e integrações do Git no ramo.
settings.protect_disable_push=Desabilitar envios
@@ -2402,7 +2402,7 @@ settings.protect_patterns=Padrões
settings.protect_protected_file_patterns=Padrões de ficheiros protegidos (separados com ponto e vírgula ';'):
settings.protect_protected_file_patterns_desc=Ficheiros protegidos não podem ser modificados imediatamente, mesmo que o utilizador tenha direitos para adicionar, editar ou eliminar ficheiros neste ramo. Múltiplos padrões podem ser separados com ponto e vírgula (';'). Veja a documentação em <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> para ver a sintaxe. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.protect_unprotected_file_patterns=Padrões de ficheiros desprotegidos (separados com ponto e vírgula ';'):
settings.protect_unprotected_file_patterns_desc=Ficheiros desprotegidos que podem ser modificados imediatamente se o utilizador tiver direitos de escrita, contornando a restrição no envio. Múltiplos padrões podem ser separados com ponto e vírgula (';'). Veja a documentação em <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> para ver a sintaxe. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.protect_unprotected_file_patterns_desc=Ficheiros desprotegidos que podem ser modificados imediatamente se o utilizador tiver direitos de escrita, contornando a restrição no envio. Padrões múltiplos podem ser separados com ponto e vírgula (';'). Veja a documentação em <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> para ver a sintaxe. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.add_protected_branch=Habilitar salvaguarda
settings.delete_protected_branch=Desabilitar salvaguarda
settings.update_protect_branch_success=A salvaguarda do ramo "%s" foi modificada.
@@ -2418,7 +2418,7 @@ settings.block_outdated_branch=Bloquear integração se o pedido de integração
settings.block_outdated_branch_desc=A integração não será possível quando o ramo de topo estiver abaixo do ramo base.
settings.default_branch_desc=Escolha um ramo do repositório como sendo o predefinido para pedidos de integração e cometimentos:
settings.merge_style_desc=Estilos de integração
settings.default_merge_style_desc=Tipo de integração predefinido para pedidos de integração:
settings.default_merge_style_desc=Tipo de integração predefinido
settings.choose_branch=Escolha um ramo…
settings.no_protected_branch=Não existem ramos protegidos.
settings.edit_protected_branch=Editar
@@ -2788,7 +2788,7 @@ self_check=Auto-verificação
identity_access=Identidade e acesso
users=Contas de utilizador
organizations=Organizações
assets=Recursos de código
assets=Recursos do código-fonte
repositories=Repositórios
hooks=Automatismos web
integrations=Integrações
@@ -2869,14 +2869,14 @@ dashboard.mspan_structures_obtained=Estruturas MSpan obtidas
dashboard.mcache_structures_usage=Uso das estruturas MCache
dashboard.mcache_structures_obtained=Estruturas MCache obtidas
dashboard.profiling_bucket_hash_table_obtained=Perfil obtido da tabela de hash do balde
dashboard.gc_metadata_obtained=Metadados da recolha de lixo obtidos
dashboard.gc_metadata_obtained=Metadados obtidos da recolha de lixo
dashboard.other_system_allocation_obtained=Outras alocações de sistema obtidas
dashboard.next_gc_recycle=Próxima reciclagem da recolha de lixo
dashboard.last_gc_time=Tempo decorrido desde a última recolha de lixo
dashboard.total_gc_time=Pausa total da recolha de lixo
dashboard.total_gc_pause=Pausa total da recolha de lixo
dashboard.last_gc_pause=Última pausa da recolha de lixo
dashboard.gc_times=Tempos da recolha de lixo
dashboard.gc_times=N.º de recolhas de lixo
dashboard.delete_old_actions=Eliminar todas as operações antigas da base de dados
dashboard.delete_old_actions.started=Foi iniciado o processo de eliminação de todas as operações antigas da base de dados.
dashboard.update_checker=Verificador de novas versões
@@ -3025,7 +3025,7 @@ auths.attribute_surname=Atributo do Sobrenome
auths.attribute_mail=Atributo do email
auths.attribute_ssh_public_key=Atributo da chave pública SSH
auths.attribute_avatar=Atributo do avatar
auths.attributes_in_bind=Buscar os atributos no contexto de Bind DN
auths.attributes_in_bind=Buscar atributos no contexto do Bind DN
auths.allow_deactivate_all=Permitir que um resultado de pesquisa vazio desabilite todos os utilizadores
auths.use_paged_search=Usar pesquisa paginada
auths.search_page_size=Tamanho da página
@@ -3224,7 +3224,7 @@ config.session_config=Configuração de sessão
config.session_provider=Fornecedor da sessão
config.provider_config=Configuração do fornecedor
config.cookie_name=Nome do cookie
config.gc_interval_time=Intervalo da recolha do lixo
config.gc_interval_time=Intervalo de tempo entre recolhas do lixo
config.session_life_time=Tempo de vida da sessão
config.https_only=Apenas HTTPS
config.cookie_life_time=Tempo de vida do cookie

+ 102
- 102
web_src/js/features/imagediff.js View File

@@ -1,6 +1,6 @@
import $ from 'jquery';
import {GET} from '../modules/fetch.js';
import {hideElem, loadElem} from '../utils/dom.js';
import {hideElem, loadElem, queryElemChildren} from '../utils/dom.js';
import {parseDom} from '../utils.js';

function getDefaultSvgBoundsIfUndefined(text, src) {
@@ -38,36 +38,36 @@ function getDefaultSvgBoundsIfUndefined(text, src) {
return null;
}

export function initImageDiff() {
function createContext(image1, image2) {
const size1 = {
width: image1 && image1.width || 0,
height: image1 && image1.height || 0,
};
const size2 = {
width: image2 && image2.width || 0,
height: image2 && image2.height || 0,
};
const max = {
width: Math.max(size2.width, size1.width),
height: Math.max(size2.height, size1.height),
};

return {
$image1: $(image1),
$image2: $(image2),
size1,
size2,
max,
ratio: [
Math.floor(max.width - size1.width) / 2,
Math.floor(max.height - size1.height) / 2,
Math.floor(max.width - size2.width) / 2,
Math.floor(max.height - size2.height) / 2,
],
};
}
function createContext(imageAfter, imageBefore) {
const sizeAfter = {
width: imageAfter?.width || 0,
height: imageAfter?.height || 0,
};
const sizeBefore = {
width: imageBefore?.width || 0,
height: imageBefore?.height || 0,
};
const maxSize = {
width: Math.max(sizeBefore.width, sizeAfter.width),
height: Math.max(sizeBefore.height, sizeAfter.height),
};

return {
imageAfter,
imageBefore,
sizeAfter,
sizeBefore,
maxSize,
ratio: [
Math.floor(maxSize.width - sizeAfter.width) / 2,
Math.floor(maxSize.height - sizeAfter.height) / 2,
Math.floor(maxSize.width - sizeBefore.width) / 2,
Math.floor(maxSize.height - sizeBefore.height) / 2,
],
};
}

export function initImageDiff() {
$('.image-diff:not([data-image-diff-loaded])').each(async function() {
const $container = $(this);
this.setAttribute('data-image-diff-loaded', 'true');
@@ -116,94 +116,96 @@ export function initImageDiff() {
initOverlay(createContext($imagesAfter[2], $imagesBefore[2]));
}

this.querySelector(':scope > .image-diff-tabs')?.classList.remove('is-loading');
queryElemChildren(this, '.image-diff-tabs', (el) => el.classList.remove('is-loading'));

function initSideBySide(container, sizes) {
let factor = 1;
if (sizes.max.width > (diffContainerWidth - 24) / 2) {
factor = (diffContainerWidth - 24) / 2 / sizes.max.width;
if (sizes.maxSize.width > (diffContainerWidth - 24) / 2) {
factor = (diffContainerWidth - 24) / 2 / sizes.maxSize.width;
}

const widthChanged = sizes.$image1.length !== 0 && sizes.$image2.length !== 0 && sizes.$image1[0].naturalWidth !== sizes.$image2[0].naturalWidth;
const heightChanged = sizes.$image1.length !== 0 && sizes.$image2.length !== 0 && sizes.$image1[0].naturalHeight !== sizes.$image2[0].naturalHeight;
if (sizes.$image1?.length) {
const widthChanged = sizes.imageAfter && sizes.imageBefore && sizes.imageAfter.naturalWidth !== sizes.imageBefore.naturalWidth;
const heightChanged = sizes.imageAfter && sizes.imageBefore && sizes.imageAfter.naturalHeight !== sizes.imageBefore.naturalHeight;
if (sizes.imageAfter) {
const boundsInfoAfterWidth = container.querySelector('.bounds-info-after .bounds-info-width');
boundsInfoAfterWidth.textContent = `${sizes.$image1[0].naturalWidth}px`;
if (widthChanged) boundsInfoAfterWidth.classList.add('green');

if (boundsInfoAfterWidth) {
boundsInfoAfterWidth.textContent = `${sizes.imageAfter.naturalWidth}px`;
boundsInfoAfterWidth.classList.toggle('green', widthChanged);
}
const boundsInfoAfterHeight = container.querySelector('.bounds-info-after .bounds-info-height');
boundsInfoAfterHeight.textContent = `${sizes.$image1[0].naturalHeight}px`;
if (heightChanged) boundsInfoAfterHeight.classList.add('green');
if (boundsInfoAfterHeight) {
boundsInfoAfterHeight.textContent = `${sizes.imageAfter.naturalHeight}px`;
boundsInfoAfterHeight.classList.toggle('green', heightChanged);
}
}

if (sizes.$image2?.length) {
if (sizes.imageBefore) {
const boundsInfoBeforeWidth = container.querySelector('.bounds-info-before .bounds-info-width');
boundsInfoBeforeWidth.textContent = `${sizes.$image2[0].naturalWidth}px`;
if (widthChanged) boundsInfoBeforeWidth.classList.add('red');

if (boundsInfoBeforeWidth) {
boundsInfoBeforeWidth.textContent = `${sizes.imageBefore.naturalWidth}px`;
boundsInfoBeforeWidth.classList.toggle('red', widthChanged);
}
const boundsInfoBeforeHeight = container.querySelector('.bounds-info-before .bounds-info-height');
boundsInfoBeforeHeight.textContent = `${sizes.$image2[0].naturalHeight}px`;
if (heightChanged) boundsInfoBeforeHeight.classList.add('red');
if (boundsInfoBeforeHeight) {
boundsInfoBeforeHeight.textContent = `${sizes.imageBefore.naturalHeight}px`;
boundsInfoBeforeHeight.classList.add('red', heightChanged);
}
}

const image1 = sizes.$image1[0];
if (image1) {
const container = image1.parentNode;
image1.style.width = `${sizes.size1.width * factor}px`;
image1.style.height = `${sizes.size1.height * factor}px`;
if (sizes.imageAfter) {
const container = sizes.imageAfter.parentNode;
sizes.imageAfter.style.width = `${sizes.sizeAfter.width * factor}px`;
sizes.imageAfter.style.height = `${sizes.sizeAfter.height * factor}px`;
container.style.margin = '10px auto';
container.style.width = `${sizes.size1.width * factor + 2}px`;
container.style.height = `${sizes.size1.height * factor + 2}px`;
container.style.width = `${sizes.sizeAfter.width * factor + 2}px`;
container.style.height = `${sizes.sizeAfter.height * factor + 2}px`;
}

const image2 = sizes.$image2[0];
if (image2) {
const container = image2.parentNode;
image2.style.width = `${sizes.size2.width * factor}px`;
image2.style.height = `${sizes.size2.height * factor}px`;
if (sizes.imageBefore) {
const container = sizes.imageBefore.parentNode;
sizes.imageBefore.style.width = `${sizes.sizeBefore.width * factor}px`;
sizes.imageBefore.style.height = `${sizes.sizeBefore.height * factor}px`;
container.style.margin = '10px auto';
container.style.width = `${sizes.size2.width * factor + 2}px`;
container.style.height = `${sizes.size2.height * factor + 2}px`;
container.style.width = `${sizes.sizeBefore.width * factor + 2}px`;
container.style.height = `${sizes.sizeBefore.height * factor + 2}px`;
}
}

function initSwipe(sizes) {
let factor = 1;
if (sizes.max.width > diffContainerWidth - 12) {
factor = (diffContainerWidth - 12) / sizes.max.width;
if (sizes.maxSize.width > diffContainerWidth - 12) {
factor = (diffContainerWidth - 12) / sizes.maxSize.width;
}

const image1 = sizes.$image1[0];
if (image1) {
const container = image1.parentNode;
if (sizes.imageAfter) {
const container = sizes.imageAfter.parentNode;
const swipeFrame = container.parentNode;
image1.style.width = `${sizes.size1.width * factor}px`;
image1.style.height = `${sizes.size1.height * factor}px`;
sizes.imageAfter.style.width = `${sizes.sizeAfter.width * factor}px`;
sizes.imageAfter.style.height = `${sizes.sizeAfter.height * factor}px`;
container.style.margin = `0px ${sizes.ratio[0] * factor}px`;
container.style.width = `${sizes.size1.width * factor + 2}px`;
container.style.height = `${sizes.size1.height * factor + 2}px`;
container.style.width = `${sizes.sizeAfter.width * factor + 2}px`;
container.style.height = `${sizes.sizeAfter.height * factor + 2}px`;
swipeFrame.style.padding = `${sizes.ratio[1] * factor}px 0 0 0`;
swipeFrame.style.width = `${sizes.max.width * factor + 2}px`;
swipeFrame.style.width = `${sizes.maxSize.width * factor + 2}px`;
}

const image2 = sizes.$image2[0];
if (image2) {
const container = image2.parentNode;
if (sizes.imageBefore) {
const container = sizes.imageBefore.parentNode;
const swipeFrame = container.parentNode;
image2.style.width = `${sizes.size2.width * factor}px`;
image2.style.height = `${sizes.size2.height * factor}px`;
sizes.imageBefore.style.width = `${sizes.sizeBefore.width * factor}px`;
sizes.imageBefore.style.height = `${sizes.sizeBefore.height * factor}px`;
container.style.margin = `${sizes.ratio[3] * factor}px ${sizes.ratio[2] * factor}px`;
container.style.width = `${sizes.size2.width * factor + 2}px`;
container.style.height = `${sizes.size2.height * factor + 2}px`;
swipeFrame.style.width = `${sizes.max.width * factor + 2}px`;
swipeFrame.style.height = `${sizes.max.height * factor + 2}px`;
container.style.width = `${sizes.sizeBefore.width * factor + 2}px`;
container.style.height = `${sizes.sizeBefore.height * factor + 2}px`;
swipeFrame.style.width = `${sizes.maxSize.width * factor + 2}px`;
swipeFrame.style.height = `${sizes.maxSize.height * factor + 2}px`;
}

// extra height for inner "position: absolute" elements
const swipe = $container.find('.diff-swipe')[0];
if (swipe) {
swipe.style.width = `${sizes.max.width * factor + 2}px`;
swipe.style.height = `${sizes.max.height * factor + 30}px`;
swipe.style.width = `${sizes.maxSize.width * factor + 2}px`;
swipe.style.height = `${sizes.maxSize.height * factor + 30}px`;
}

$container.find('.swipe-bar').on('mousedown', function(e) {
@@ -229,39 +231,37 @@ export function initImageDiff() {

function initOverlay(sizes) {
let factor = 1;
if (sizes.max.width > diffContainerWidth - 12) {
factor = (diffContainerWidth - 12) / sizes.max.width;
if (sizes.maxSize.width > diffContainerWidth - 12) {
factor = (diffContainerWidth - 12) / sizes.maxSize.width;
}

const image1 = sizes.$image1[0];
if (image1) {
const container = image1.parentNode;
image1.style.width = `${sizes.size1.width * factor}px`;
image1.style.height = `${sizes.size1.height * factor}px`;
if (sizes.imageAfter) {
const container = sizes.imageAfter.parentNode;
sizes.imageAfter.style.width = `${sizes.sizeAfter.width * factor}px`;
sizes.imageAfter.style.height = `${sizes.sizeAfter.height * factor}px`;
container.style.margin = `${sizes.ratio[1] * factor}px ${sizes.ratio[0] * factor}px`;
container.style.width = `${sizes.size1.width * factor + 2}px`;
container.style.height = `${sizes.size1.height * factor + 2}px`;
container.style.width = `${sizes.sizeAfter.width * factor + 2}px`;
container.style.height = `${sizes.sizeAfter.height * factor + 2}px`;
}

const image2 = sizes.$image2[0];
if (image2) {
const container = image2.parentNode;
if (sizes.imageBefore) {
const container = sizes.imageBefore.parentNode;
const overlayFrame = container.parentNode;
image2.style.width = `${sizes.size2.width * factor}px`;
image2.style.height = `${sizes.size2.height * factor}px`;
sizes.imageBefore.style.width = `${sizes.sizeBefore.width * factor}px`;
sizes.imageBefore.style.height = `${sizes.sizeBefore.height * factor}px`;
container.style.margin = `${sizes.ratio[3] * factor}px ${sizes.ratio[2] * factor}px`;
container.style.width = `${sizes.size2.width * factor + 2}px`;
container.style.height = `${sizes.size2.height * factor + 2}px`;
container.style.width = `${sizes.sizeBefore.width * factor + 2}px`;
container.style.height = `${sizes.sizeBefore.height * factor + 2}px`;

// some inner elements are `position: absolute`, so the container's height must be large enough
overlayFrame.style.width = `${sizes.max.width * factor + 2}px`;
overlayFrame.style.height = `${sizes.max.height * factor + 2}px`;
overlayFrame.style.width = `${sizes.maxSize.width * factor + 2}px`;
overlayFrame.style.height = `${sizes.maxSize.height * factor + 2}px`;
}

const rangeInput = $container[0].querySelector('input[type="range"]');
function updateOpacity() {
if (sizes?.$image1?.[0]) {
sizes.$image1[0].parentNode.style.opacity = `${rangeInput.value / 100}`;
if (sizes.imageAfter) {
sizes.imageAfter.parentNode.style.opacity = `${rangeInput.value / 100}`;
}
}
rangeInput?.addEventListener('input', updateOpacity);

Loading…
Cancel
Save