From 6cc8aed7377660e7288298af4ec4d70a43d912f2 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 27 Apr 2022 00:01:42 +0800 Subject: [PATCH 01/21] Fix two typos (#19504) --- docs/content/doc/installation/with-docker.fr-fr.md | 2 +- models/migrations/migrations.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/doc/installation/with-docker.fr-fr.md b/docs/content/doc/installation/with-docker.fr-fr.md index 0011ba2ff442c..176abf7a129d8 100644 --- a/docs/content/doc/installation/with-docker.fr-fr.md +++ b/docs/content/doc/installation/with-docker.fr-fr.md @@ -43,7 +43,7 @@ Vous devriez avoir une instance fonctionnelle de Gitea. Pour accèder à l'inter ## Named Volumes -Ce guide aboutira à une installation avec les données Gita et PostgreSQL stockées dans des volumes nommés. Cela permet une sauvegarde, une restauration et des mises à niveau en toute simplicité. +Ce guide aboutira à une installation avec les données Gitea et PostgreSQL stockées dans des volumes nommés. Cela permet une sauvegarde, une restauration et des mises à niveau en toute simplicité. ### The Database diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index de1d41e71a848..ba8ca85bc8d93 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -460,7 +460,7 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t // Downgrading Gitea's database version not supported if int(v-minDBVersion) > len(migrations) { - msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Gita, you can not use the newer database for this old Gitea release (%d).", v, minDBVersion+len(migrations)) + msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Gitea, you can not use the newer database for this old Gitea release (%d).", v, minDBVersion+len(migrations)) msg += "\nGitea will exit to keep your database safe and unchanged. Please use the correct Gitea release, do not change the migration version manually (incorrect manual operation may lose data)." if !setting.IsProd { msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", minDBVersion+len(migrations)) From 3c140f0d424bc987493439eb600b221a927a933d Mon Sep 17 00:00:00 2001 From: John Olheiser Date: Tue, 26 Apr 2022 12:15:45 -0500 Subject: [PATCH 02/21] Use router param for filepath in GetRawFile (#19499) * Use router param for filepath Signed-off-by: jolheiser * Move TreePath back into RepoRefForAPI Signed-off-by: jolheiser Co-authored-by: Lunny Xiao Co-authored-by: 6543 <6543@obermui.de> --- modules/context/api.go | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/context/api.go b/modules/context/api.go index 41d559f5b1c5f..7d281b998a7df 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -362,6 +362,7 @@ func RepoRefForAPI(next http.Handler) http.Handler { return } ctx.Repo.Commit = commit + ctx.Repo.TreePath = ctx.Params("*") return } From 2347c9ebbe1cf180cfa714ea0118b79df1ced2cd Mon Sep 17 00:00:00 2001 From: parnic Date: Tue, 26 Apr 2022 14:09:46 -0500 Subject: [PATCH 03/21] Allow commit status popup on /pulls page (#19507) * Allow commit status popup on /pulls page The /pulls page doesn't contain a "repository" element, so the early-out here was preventing the commit status popup hook from working. However, the only thing the .repository element is being used for here is determining whether the popup should be on the right or on the left, so we don't actually need the element to exist for the hook to work. Pull request #19375 allows the statuses on /pulls pages to appear clickable, but this commit is required to make the popup actually work there. * Move commit statuses popup hook to dedicated func * Add missing import --- web_src/js/features/repo-commit.js | 13 +++++++++++++ web_src/js/features/repo-legacy.js | 12 ------------ web_src/js/index.js | 8 +++++++- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/web_src/js/features/repo-commit.js b/web_src/js/features/repo-commit.js index 9a8f1a159509b..a911c173929a4 100644 --- a/web_src/js/features/repo-commit.js +++ b/web_src/js/features/repo-commit.js @@ -49,3 +49,16 @@ export function initRepoCommitLastCommitLoader() { }); }); } + +export function initCommitStatuses() { + $('.commit-statuses-trigger').each(function () { + const positionRight = $('.repository.file.list').length > 0 || $('.repository.diff').length > 0; + const popupPosition = positionRight ? 'right center' : 'left center'; + $(this) + .popup({ + on: 'click', + lastResort: popupPosition, // prevent error message "Popup does not fit within the boundaries of the viewport" + position: popupPosition, + }); + }); +} diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js index 185a0014fae2d..b7e6206e53a95 100644 --- a/web_src/js/features/repo-legacy.js +++ b/web_src/js/features/repo-legacy.js @@ -423,18 +423,6 @@ export function initRepository() { } - // Commit statuses - $('.commit-statuses-trigger').each(function () { - const positionRight = $('.repository.file.list').length > 0 || $('.repository.diff').length > 0; - const popupPosition = positionRight ? 'right center' : 'left center'; - $(this) - .popup({ - on: 'click', - lastResort: popupPosition, // prevent error message "Popup does not fit within the boundaries of the viewport" - position: popupPosition, - }); - }); - // File list and commits if ($('.repository.file.list').length > 0 || $('.branch-dropdown').length > 0 || $('.repository.commits').length > 0 || $('.repository.release').length > 0) { diff --git a/web_src/js/index.js b/web_src/js/index.js index 18b949e4e62f7..f5d72aff93d4d 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -38,7 +38,11 @@ import { initRepoPullRequestMergeInstruction, initRepoPullRequestReview, } from './features/repo-issue.js'; -import {initRepoEllipsisButton, initRepoCommitLastCommitLoader} from './features/repo-commit.js'; +import { + initRepoEllipsisButton, + initRepoCommitLastCommitLoader, + initCommitStatuses, +} from './features/repo-commit.js'; import { checkAppUrl, initFootLanguageMenu, @@ -165,6 +169,8 @@ $(document).ready(() => { initRepoWikiForm(); initRepository(); + initCommitStatuses(); + initUserAuthLinkAccountView(); initUserAuthOauth2(); initUserAuthWebAuthn(); From 6dd36379f24142198671e7c3f0ae44c3f579d21d Mon Sep 17 00:00:00 2001 From: zeripath Date: Tue, 26 Apr 2022 21:28:45 +0100 Subject: [PATCH 04/21] Unset git author/committer variables when running integration tests (#19512) TestAPIGitTag (and likely others) will fail if the running environment contains GIT_AUTHOR_NAME and other env variables like it. This PR simply unsets these when running the integration tests. Fix #14247 Signed-off-by: Andrew Thornton --- integrations/integration_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/integrations/integration_test.go b/integrations/integration_test.go index 8d2bfe9383f9c..228b4123724a2 100644 --- a/integrations/integration_test.go +++ b/integrations/integration_test.go @@ -112,6 +112,13 @@ func TestMain(m *testing.M) { } } + os.Unsetenv("GIT_AUTHOR_NAME") + os.Unsetenv("GIT_AUTHOR_EMAIL") + os.Unsetenv("GIT_AUTHOR_DATE") + os.Unsetenv("GIT_COMMITTER_NAME") + os.Unsetenv("GIT_COMMITTER_EMAIL") + os.Unsetenv("GIT_COMMITTER_DATE") + err := unittest.InitFixtures( unittest.FixturesOptions{ Dir: filepath.Join(filepath.Dir(setting.AppPath), "models/fixtures/"), From e4274f640ccf63b26adf409c9bc14897610fb81a Mon Sep 17 00:00:00 2001 From: KN4CK3R Date: Tue, 26 Apr 2022 22:30:51 +0200 Subject: [PATCH 05/21] Allow package dump skipping (#19506) * Added addReader to support verbose. * Allow skipping packages. * Updated docs. * Update cmd/dump.go Co-authored-by: wxiaoguang Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: wxiaoguang --- cmd/dump.go | 58 ++++++++++++-------- docs/content/doc/usage/command-line.en-us.md | 5 ++ 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/cmd/dump.go b/cmd/dump.go index f72ef05e948f9..ea41c0c029d9b 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -7,6 +7,7 @@ package cmd import ( "fmt" + "io" "os" "path" "path/filepath" @@ -25,10 +26,21 @@ import ( "github.com/urfave/cli" ) -func addFile(w archiver.Writer, filePath, absPath string, verbose bool) error { +func addReader(w archiver.Writer, r io.ReadCloser, info os.FileInfo, customName string, verbose bool) error { if verbose { - log.Info("Adding file %s\n", filePath) + log.Info("Adding file %s", customName) } + + return w.Write(archiver.File{ + FileInfo: archiver.FileInfo{ + FileInfo: info, + CustomName: customName, + }, + ReadCloser: r, + }) +} + +func addFile(w archiver.Writer, filePath, absPath string, verbose bool) error { file, err := os.Open(absPath) if err != nil { return err @@ -39,13 +51,7 @@ func addFile(w archiver.Writer, filePath, absPath string, verbose bool) error { return err } - return w.Write(archiver.File{ - FileInfo: archiver.FileInfo{ - FileInfo: fileInfo, - CustomName: filePath, - }, - ReadCloser: file, - }) + return addReader(w, file, fileInfo, filePath, verbose) } func isSubdir(upper, lower string) (bool, error) { @@ -136,6 +142,10 @@ It can be used for backup and capture Gitea server image to send to maintainer`, Name: "skip-attachment-data", Usage: "Skip attachment data", }, + cli.BoolFlag{ + Name: "skip-package-data", + Usage: "Skip package data", + }, cli.GenericFlag{ Name: "type", Value: outputTypeEnum, @@ -241,13 +251,7 @@ func runDump(ctx *cli.Context) error { return err } - return w.Write(archiver.File{ - FileInfo: archiver.FileInfo{ - FileInfo: info, - CustomName: path.Join("data", "lfs", objPath), - }, - ReadCloser: object, - }) + return addReader(w, object, info, path.Join("data", "lfs", objPath), verbose) }); err != nil { fatal("Failed to dump LFS objects: %v", err) } @@ -326,6 +330,7 @@ func runDump(ctx *cli.Context) error { excludes = append(excludes, setting.RepoRootPath) excludes = append(excludes, setting.LFS.Path) excludes = append(excludes, setting.Attachment.Path) + excludes = append(excludes, setting.Packages.Path) excludes = append(excludes, setting.LogRootPath) excludes = append(excludes, absFileName) if err := addRecursiveExclude(w, "data", setting.AppDataPath, excludes, verbose); err != nil { @@ -341,17 +346,24 @@ func runDump(ctx *cli.Context) error { return err } - return w.Write(archiver.File{ - FileInfo: archiver.FileInfo{ - FileInfo: info, - CustomName: path.Join("data", "attachments", objPath), - }, - ReadCloser: object, - }) + return addReader(w, object, info, path.Join("data", "attachments", objPath), verbose) }); err != nil { fatal("Failed to dump attachments: %v", err) } + if ctx.IsSet("skip-package-data") && ctx.Bool("skip-package-data") { + log.Info("Skip dumping package data") + } else if err := storage.Packages.IterateObjects(func(objPath string, object storage.Object) error { + info, err := object.Stat() + if err != nil { + return err + } + + return addReader(w, object, info, path.Join("data", "packages", objPath), verbose) + }); err != nil { + fatal("Failed to dump packages: %v", err) + } + // Doesn't check if LogRootPath exists before processing --skip-log intentionally, // ensuring that it's clear the dump is skipped whether the directory's initialized // yet or not. diff --git a/docs/content/doc/usage/command-line.en-us.md b/docs/content/doc/usage/command-line.en-us.md index 3b75a5c843d20..8cc420ed11b1f 100644 --- a/docs/content/doc/usage/command-line.en-us.md +++ b/docs/content/doc/usage/command-line.en-us.md @@ -313,8 +313,13 @@ in the current directory. - `--tempdir path`, `-t path`: Path to the temporary directory used. Optional. (default: /tmp). - `--skip-repository`, `-R`: Skip the repository dumping. Optional. - `--skip-custom-dir`: Skip dumping of the custom dir. Optional. + - `--skip-lfs-data`: Skip dumping of LFS data. Optional. + - `--skip-attachment-data`: Skip dumping of attachment data. Optional. + - `--skip-package-data`: Skip dumping of package data. Optional. + - `--skip-log`: Skip dumping of log data. Optional. - `--database`, `-d`: Specify the database SQL syntax. Optional. - `--verbose`, `-V`: If provided, shows additional details. Optional. + - `--type`: Set the dump output format. Optional. (default: zip) - Examples: - `gitea dump` - `gitea dump --verbose` From d71df01077fbd9366e38150e0b037008c3f808de Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 27 Apr 2022 04:31:15 +0800 Subject: [PATCH 06/21] Refactor readme file renderer (#19502) * Refactor readme file renderer * improve --- routers/web/repo/view.go | 237 +++++++++++++++++++++------------------ 1 file changed, 125 insertions(+), 112 deletions(-) diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 0faa01d573ce0..168927d101ae4 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -146,6 +146,21 @@ func renderDirectory(ctx *context.Context, treeLink string) { ctx.Data["Title"] = ctx.Tr("repo.file.title", ctx.Repo.Repository.Name+"/"+path.Base(ctx.Repo.TreePath), ctx.Repo.RefName) } + // Check permission to add or upload new file. + if ctx.Repo.CanWrite(unit_model.TypeCode) && ctx.Repo.IsViewBranch { + ctx.Data["CanAddFile"] = !ctx.Repo.Repository.IsArchived + ctx.Data["CanUploadFile"] = setting.Repository.Upload.Enabled && !ctx.Repo.Repository.IsArchived + } + + readmeFile, readmeTreelink := findReadmeFile(ctx, entries, treeLink) + if ctx.Written() || readmeFile == nil { + return + } + + renderReadmeFile(ctx, readmeFile, readmeTreelink) +} + +func findReadmeFile(ctx *context.Context, entries git.Entries, treeLink string) (*namedBlob, string) { // 3 for the extensions in exts[] in order // the last one is for a readme that doesn't // strictly match an extension @@ -183,7 +198,7 @@ func renderDirectory(ctx *context.Context, treeLink string) { target, err = entry.FollowLinks() if err != nil && !git.IsErrBadLink(err) { ctx.ServerError("FollowLinks", err) - return + return nil, "" } } log.Debug("%t", target == nil) @@ -205,7 +220,7 @@ func renderDirectory(ctx *context.Context, treeLink string) { entry, err = entry.FollowLinks() if err != nil && !git.IsErrBadLink(err) { ctx.ServerError("FollowLinks", err) - return + return nil, "" } } if entry != nil && (entry.IsExecutable() || entry.IsRegular()) { @@ -236,7 +251,7 @@ func renderDirectory(ctx *context.Context, treeLink string) { readmeFile, err = getReadmeFileFromPath(ctx.Repo.Commit, entry.GetSubJumpablePathName()) if err != nil { ctx.ServerError("getReadmeFileFromPath", err) - return + return nil, "" } if readmeFile != nil { readmeFile.name = entry.Name() + "/" + readmeFile.name @@ -245,129 +260,127 @@ func renderDirectory(ctx *context.Context, treeLink string) { } } } + return readmeFile, readmeTreelink +} - if readmeFile != nil { - ctx.Data["RawFileLink"] = "" - ctx.Data["ReadmeInList"] = true - ctx.Data["ReadmeExist"] = true - ctx.Data["FileIsSymlink"] = readmeFile.isSymlink +func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelink string) { + ctx.Data["RawFileLink"] = "" + ctx.Data["ReadmeInList"] = true + ctx.Data["ReadmeExist"] = true + ctx.Data["FileIsSymlink"] = readmeFile.isSymlink - dataRc, err := readmeFile.blob.DataAsync() - if err != nil { - ctx.ServerError("Data", err) - return - } - defer dataRc.Close() - - buf := make([]byte, 1024) - n, _ := util.ReadAtMost(dataRc, buf) - buf = buf[:n] - - st := typesniffer.DetectContentType(buf) - isTextFile := st.IsText() - - ctx.Data["FileIsText"] = isTextFile - ctx.Data["FileName"] = readmeFile.name - fileSize := int64(0) - isLFSFile := false - ctx.Data["IsLFSFile"] = false - - // FIXME: what happens when README file is an image? - if isTextFile && setting.LFS.StartServer { - pointer, _ := lfs.ReadPointerFromBuffer(buf) - if pointer.IsValid() { - meta, err := models.GetLFSMetaObjectByOid(ctx.Repo.Repository.ID, pointer.Oid) - if err != nil && err != models.ErrLFSObjectNotExist { - ctx.ServerError("GetLFSMetaObject", err) - return - } - if meta != nil { - ctx.Data["IsLFSFile"] = true - isLFSFile = true + dataRc, err := readmeFile.blob.DataAsync() + if err != nil { + ctx.ServerError("Data", err) + return + } + defer dataRc.Close() - // OK read the lfs object - var err error - dataRc, err = lfs.ReadMetaObject(pointer) - if err != nil { - ctx.ServerError("ReadMetaObject", err) - return - } - defer dataRc.Close() + buf := make([]byte, 1024) + n, _ := util.ReadAtMost(dataRc, buf) + buf = buf[:n] - buf = make([]byte, 1024) - n, err = util.ReadAtMost(dataRc, buf) - if err != nil { - ctx.ServerError("Data", err) - return - } - buf = buf[:n] + st := typesniffer.DetectContentType(buf) + isTextFile := st.IsText() - st = typesniffer.DetectContentType(buf) - isTextFile = st.IsText() - ctx.Data["IsTextFile"] = isTextFile + ctx.Data["FileIsText"] = isTextFile + ctx.Data["FileName"] = readmeFile.name + fileSize := int64(0) + isLFSFile := false + ctx.Data["IsLFSFile"] = false - fileSize = meta.Size - ctx.Data["FileSize"] = meta.Size - filenameBase64 := base64.RawURLEncoding.EncodeToString([]byte(readmeFile.name)) - ctx.Data["RawFileLink"] = fmt.Sprintf("%s.git/info/lfs/objects/%s/%s", ctx.Repo.Repository.HTMLURL(), url.PathEscape(meta.Oid), url.PathEscape(filenameBase64)) - } + // FIXME: what happens when README file is an image? + if isTextFile && setting.LFS.StartServer { + pointer, _ := lfs.ReadPointerFromBuffer(buf) + if pointer.IsValid() { + meta, err := models.GetLFSMetaObjectByOid(ctx.Repo.Repository.ID, pointer.Oid) + if err != nil && err != models.ErrLFSObjectNotExist { + ctx.ServerError("GetLFSMetaObject", err) + return } - } - - if !isLFSFile { - fileSize = readmeFile.blob.Size() - } + if meta != nil { + ctx.Data["IsLFSFile"] = true + isLFSFile = true - if isTextFile { - if fileSize >= setting.UI.MaxDisplayFileSize { - // Pretend that this is a normal text file to display 'This file is too large to be shown' - ctx.Data["IsFileTooLarge"] = true - ctx.Data["IsTextFile"] = true - ctx.Data["FileSize"] = fileSize - } else { - rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc)) - - if markupType := markup.Type(readmeFile.name); markupType != "" { - ctx.Data["IsMarkup"] = true - ctx.Data["MarkupType"] = string(markupType) - var result strings.Builder - err := markup.Render(&markup.RenderContext{ - Ctx: ctx, - Filename: readmeFile.name, - URLPrefix: readmeTreelink, - Metas: ctx.Repo.Repository.ComposeDocumentMetas(), - GitRepo: ctx.Repo.GitRepo, - }, rd, &result) - if err != nil { - log.Error("Render failed: %v then fallback", err) - buf := &bytes.Buffer{} - ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, buf) - ctx.Data["FileContent"] = strings.ReplaceAll( - gotemplate.HTMLEscapeString(buf.String()), "\n", `
`, - ) - } else { - ctx.Data["EscapeStatus"], ctx.Data["FileContent"] = charset.EscapeControlString(result.String()) - } - } else { - ctx.Data["IsRenderedHTML"] = true - buf := &bytes.Buffer{} - ctx.Data["EscapeStatus"], err = charset.EscapeControlReader(rd, buf) - if err != nil { - log.Error("Read failed: %v", err) - } + // OK read the lfs object + var err error + dataRc, err = lfs.ReadMetaObject(pointer) + if err != nil { + ctx.ServerError("ReadMetaObject", err) + return + } + defer dataRc.Close() - ctx.Data["FileContent"] = strings.ReplaceAll( - gotemplate.HTMLEscapeString(buf.String()), "\n", `
`, - ) + buf = make([]byte, 1024) + n, err = util.ReadAtMost(dataRc, buf) + if err != nil { + ctx.ServerError("Data", err) + return } + buf = buf[:n] + + st = typesniffer.DetectContentType(buf) + isTextFile = st.IsText() + ctx.Data["IsTextFile"] = isTextFile + + fileSize = meta.Size + ctx.Data["FileSize"] = meta.Size + filenameBase64 := base64.RawURLEncoding.EncodeToString([]byte(readmeFile.name)) + ctx.Data["RawFileLink"] = fmt.Sprintf("%s.git/info/lfs/objects/%s/%s", ctx.Repo.Repository.HTMLURL(), url.PathEscape(meta.Oid), url.PathEscape(filenameBase64)) } } } - // Check permission to add or upload new file. - if ctx.Repo.CanWrite(unit_model.TypeCode) && ctx.Repo.IsViewBranch { - ctx.Data["CanAddFile"] = !ctx.Repo.Repository.IsArchived - ctx.Data["CanUploadFile"] = setting.Repository.Upload.Enabled && !ctx.Repo.Repository.IsArchived + if !isTextFile { + return + } + + if !isLFSFile { + fileSize = readmeFile.blob.Size() + } + + if fileSize >= setting.UI.MaxDisplayFileSize { + // Pretend that this is a normal text file to display 'This file is too large to be shown' + ctx.Data["IsFileTooLarge"] = true + ctx.Data["IsTextFile"] = true + ctx.Data["FileSize"] = fileSize + return + } + + rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc)) + + if markupType := markup.Type(readmeFile.name); markupType != "" { + ctx.Data["IsMarkup"] = true + ctx.Data["MarkupType"] = string(markupType) + var result strings.Builder + err := markup.Render(&markup.RenderContext{ + Ctx: ctx, + Filename: readmeFile.name, + URLPrefix: readmeTreelink, + Metas: ctx.Repo.Repository.ComposeDocumentMetas(), + GitRepo: ctx.Repo.GitRepo, + }, rd, &result) + if err != nil { + log.Error("Render failed: %v then fallback", err) + buf := &bytes.Buffer{} + ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, buf) + ctx.Data["FileContent"] = strings.ReplaceAll( + gotemplate.HTMLEscapeString(buf.String()), "\n", `
`, + ) + } else { + ctx.Data["EscapeStatus"], ctx.Data["FileContent"] = charset.EscapeControlString(result.String()) + } + } else { + ctx.Data["IsRenderedHTML"] = true + buf := &bytes.Buffer{} + ctx.Data["EscapeStatus"], err = charset.EscapeControlReader(rd, buf) + if err != nil { + log.Error("Read failed: %v", err) + } + + ctx.Data["FileContent"] = strings.ReplaceAll( + gotemplate.HTMLEscapeString(buf.String()), "\n", `
`, + ) } } From 89eec15dd90e50c36051eb3f6a2ed2616c513ad8 Mon Sep 17 00:00:00 2001 From: Gusted Date: Tue, 26 Apr 2022 20:31:58 +0000 Subject: [PATCH 07/21] By default force vertical tabs on mobile (#19486) * By default force vertical tabs on mobile - While experimenting with using vertical tabs instead of horizontal tabs on gitea for a better mobile experience, I made a recent PR(https://github.com/go-gitea/gitea/pull/19468) in order to see if there was any objections to this new behavior for the repo headers(one of the most annoying horizontal tabs). This PR had no objections and even a user commenting that this change is brilliant. - This PR now improves upon the previous PR by making this the de-facto behavior for all menu's on mobile. The only exemption is the navbar which also uses the menu but caught some layout errors with the changes. * Fix organisation * Fix repo/wiki buttons Co-authored-by: Lunny Xiao --- templates/base/head.tmpl | 2 +- templates/repo/header.tmpl | 2 +- templates/repo/home.tmpl | 2 +- templates/repo/wiki/view.tmpl | 2 +- web_src/less/_base.less | 27 +++++++++++++-------------- web_src/less/_repository.less | 15 --------------- 6 files changed, 17 insertions(+), 33 deletions(-) diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index 35157e9b954b4..f3dcfe8429f6a 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -85,7 +85,7 @@ {{template "custom/body_inner_pre" .}} {{if not .PageIsInstall}} - {{end}} -
+
{{if not (or .Repository.IsBeingCreated .Repository.IsBroken)}} {{end}} {{template "repo/sub_menu" .}} -