diff --git a/data/src/main/java/com/fastaccess/data/model/CommitLinesModel.kt b/data/src/main/java/com/fastaccess/data/model/CommitLinesModel.kt new file mode 100644 index 00000000..622c20f8 --- /dev/null +++ b/data/src/main/java/com/fastaccess/data/model/CommitLinesModel.kt @@ -0,0 +1,19 @@ +package com.fastaccess.data.model + +data class CommitLinesModel( + var text: String? = null, + var color: Int = 0, + var leftLineNo: Int = 0, + var rightLineNo: Int = 0, + var noNewLine: Boolean = false, + var position: Int = 0, + var hasCommentedOn: Boolean = false +) { + + companion object { + const val TRANSPARENT = 0 + const val ADDITION = 1 + const val DELETION = 2 + const val PATCH = 3 + } +} \ No newline at end of file diff --git a/diff/build.gradle b/diff/build.gradle index 183eed5d..f1f8dfcb 100644 --- a/diff/build.gradle +++ b/diff/build.gradle @@ -50,6 +50,7 @@ dependencies { implementation project(':resources') implementation project(':extensions') implementation project(':dagger') + implementation project(':markdown') implementation dependency.kotlin implementation dependency.supportLibraries implementation dependency.extrasLibraries diff --git a/diff/src/main/assets/diff.js b/diff/src/main/assets/diff.js deleted file mode 100644 index 50f319f2..00000000 --- a/diff/src/main/assets/diff.js +++ /dev/null @@ -1,10 +0,0 @@ -function loadDiff(diff) { - var diffHtml = Diff2Html.getPrettyHtml(diff, { - inputFormat: 'diff', - showFiles: true, - matching: 'none', - outputFormat: 'line-by-line' - }); - console.log(diffHtml); - document.getElementById("diff").innerHTML = diffHtml; -} \ No newline at end of file diff --git a/diff/src/main/assets/diff2html.css b/diff/src/main/assets/diff2html.css deleted file mode 100644 index 7d22dd4a..00000000 --- a/diff/src/main/assets/diff2html.css +++ /dev/null @@ -1,365 +0,0 @@ -/* - * - * Diff to HTML (diff2html.css) - * Author: rtfpessoa - * - */ - -.d2h-wrapper { - text-align: left; -} - -.d2h-file-header { - height: 35px; - padding: 5px 10px; - border-bottom: 1px solid #d8d8d8; - background-color: #f7f7f7; -} - -.d2h-file-stats { - display: flex; - margin-left: auto; - font-size: 14px; -} - -.d2h-lines-added { - text-align: right; - border: 1px solid #b4e2b4; - border-radius: 5px 0 0 5px; - color: #399839; - padding: 2px; - vertical-align: middle; -} - -.d2h-lines-deleted { - text-align: left; - border: 1px solid #e9aeae; - border-radius: 0 5px 5px 0; - color: #c33; - padding: 2px; - vertical-align: middle; - margin-left: 1px; -} - -.d2h-file-name-wrapper { - display: flex; - align-items: center; - width: 100%; - font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 15px; -} - -.d2h-file-name { - white-space: nowrap; - text-overflow: ellipsis; - overflow-x: hidden; -} - -.d2h-file-wrapper { - border: 1px solid #ddd; - border-radius: 3px; - margin-bottom: 1em; -} - -.d2h-diff-table { - width: 100%; - border-collapse: collapse; - font-family: "Menlo", "Consolas", monospace; - font-size: 13px; -} - -.d2h-files-diff { - display: block; - width: 100%; - height: 100%; -} - -.d2h-file-diff { - overflow-y: hidden; -} - -.d2h-file-side-diff { - display: inline-block; - overflow-x: scroll; - overflow-y: hidden; - width: 50%; - margin-right: -4px; - margin-bottom: -8px; -} - -.d2h-code-line { - display: inline-block; - white-space: nowrap; - /* Compensate for the absolute positioning of the line numbers */ - padding: 0 8em; -} - -.d2h-code-side-line { - display: inline-block; - white-space: nowrap; - /* Compensate for the absolute positioning of the line numbers */ - padding: 0 4.5em; -} - -.d2h-code-line del, -.d2h-code-side-line del { - display: inline-block; - margin-top: -1px; - text-decoration: none; - background-color: #ffb6ba; - border-radius: 0.2em; -} - -.d2h-code-line ins, -.d2h-code-side-line ins { - display: inline-block; - margin-top: -1px; - text-decoration: none; - background-color: #97f295; - border-radius: 0.2em; - text-align: left; -} - -.d2h-code-line-prefix { - display: inline; - background: none; - padding: 0; - word-wrap: normal; - white-space: pre; -} - -.d2h-code-line-ctn { - display: inline; - background: none; - padding: 0; - word-wrap: normal; - white-space: pre; -} - -.line-num1 { - box-sizing: border-box; - float: left; - width: 3.5em; - overflow: hidden; - text-overflow: ellipsis; - padding: 0 0.5em 0 0.5em; -} - -.line-num2 { - box-sizing: border-box; - float: right; - width: 3.5em; - overflow: hidden; - text-overflow: ellipsis; - padding: 0 0.5em 0 0.5em; -} - -.d2h-code-linenumber { - box-sizing: border-box; - width: 7.5em; - /* Keep the numbers fixed on line contents scroll */ - position: absolute; - display: inline-block; - background-color: #fff; - color: rgba(0, 0, 0, 0.3); - text-align: right; - border: solid #eeeeee; - border-width: 0 1px 0 1px; - cursor: pointer; -} - -.d2h-code-linenumber:after { - content: '\200b'; -} - -.d2h-code-side-linenumber { - /* Keep the numbers fixed on line contents scroll */ - position: absolute; - display: inline-block; - box-sizing: border-box; - width: 4em; - background-color: #fff; - color: rgba(0, 0, 0, 0.3); - text-align: right; - border: solid #eeeeee; - border-width: 0 1px 0 1px; - cursor: pointer; - overflow: hidden; - text-overflow: ellipsis; -} - -.d2h-code-side-linenumber:after { - content: '\200b'; -} - -.d2h-code-side-emptyplaceholder, -.d2h-emptyplaceholder { - background-color: #f1f1f1; - border-color: #e1e1e1; -} - -/* - * Changes Highlight - */ - -.d2h-del { - background-color: #fee8e9; - border-color: #e9aeae; -} - -.d2h-ins { - background-color: #dfd; - border-color: #b4e2b4; -} - -.d2h-info { - background-color: #f8fafd; - color: rgba(0, 0, 0, 0.3); - border-color: #d5e4f2; -} - -.d2h-file-diff .d2h-del.d2h-change { - background-color: #fdf2d0; -} - -.d2h-file-diff .d2h-ins.d2h-change { - background-color: #ded; -} - -/* - * File Summary List - */ - -.d2h-file-list-wrapper { - margin-bottom: 10px; -} - -.d2h-file-list-wrapper a { - text-decoration: none; - color: #3572b0; -} - -.d2h-file-list-wrapper a:visited { - color: #3572b0; -} - -.d2h-file-list-header { - text-align: left; -} - -.d2h-file-list-title { - font-weight: bold; -} - -.d2h-file-list-line { - display: flex; - text-align: left; -} - -.d2h-file-list { - display: block; - list-style: none; - padding: 0; - margin: 0; -} - -.d2h-file-list > li { - border-bottom: #ddd solid 1px; - padding: 5px 10px; - margin: 0; -} - -.d2h-file-list > li:last-child { - border-bottom: none; -} - -.d2h-file-switch { - display: none; - font-size: 10px; - cursor: pointer; -} - -.d2h-icon { - vertical-align: middle; - margin-right: 10px; - fill: currentColor; -} - -.d2h-deleted { - color: #c33; -} - -.d2h-added { - color: #399839; -} - -.d2h-changed { - color: #d0b44c; -} - -.d2h-moved { - color: #3572b0; -} - -.d2h-tag { - display: flex; - font-size: 10px; - margin-left: 5px; - padding: 0 2px; - background-color: #fff; -} - -.d2h-deleted-tag { - border: #c33 1px solid; -} - -.d2h-added-tag { - border: #399839 1px solid; -} - -.d2h-changed-tag { - border: #d0b44c 1px solid; -} - -.d2h-moved-tag { - border: #3572b0 1px solid; -} - -/* - * Selection util. - */ - -.selecting-left .d2h-code-line, -.selecting-left .d2h-code-line *, -.selecting-right td.d2h-code-linenumber, -.selecting-right td.d2h-code-linenumber *, -.selecting-left .d2h-code-side-line, -.selecting-left .d2h-code-side-line *, -.selecting-right td.d2h-code-side-linenumber, -.selecting-right td.d2h-code-side-linenumber * { - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.selecting-left .d2h-code-line::-moz-selection, -.selecting-left .d2h-code-line *::-moz-selection, -.selecting-right td.d2h-code-linenumber::-moz-selection, -.selecting-left .d2h-code-side-line::-moz-selection, -.selecting-left .d2h-code-side-line *::-moz-selection, -.selecting-right td.d2h-code-side-linenumber::-moz-selection, -.selecting-right td.d2h-code-side-linenumber *::-moz-selection { - background: transparent; -} - -.selecting-left .d2h-code-line::selection, -.selecting-left .d2h-code-line *::selection, -.selecting-right td.d2h-code-linenumber::selection, -.selecting-left .d2h-code-side-line::selection, -.selecting-left .d2h-code-side-line *::selection, -.selecting-right td.d2h-code-side-linenumber::selection, -.selecting-right td.d2h-code-side-linenumber *::selection { - background: transparent; -} \ No newline at end of file diff --git a/diff/src/main/assets/diff2html.min.js b/diff/src/main/assets/diff2html.min.js deleted file mode 100644 index be3ff536..00000000 --- a/diff/src/main/assets/diff2html.min.js +++ /dev/null @@ -1 +0,0 @@ -!function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;ivalue.length?oldValue:value}),component.value=diff.join(value)}else component.value=diff.join(newString.slice(newPos,newPos+component.count));newPos+=component.count,component.added||(oldPos+=component.count)}}var lastComponent=components[componentLen-1];return 1=newLen&&oldLen<=oldPos+1)return done([{value:this.join(newString),count:newString.length}]);function execEditLength(){for(var diagonalPath=-1*editLength;diagonalPath<=editLength;diagonalPath+=2){var basePath=void 0,addPath=bestPath[diagonalPath-1],removePath=bestPath[diagonalPath+1],_oldPos=(removePath?removePath.newPos:0)-diagonalPath;addPath&&(bestPath[diagonalPath-1]=void 0);var canAdd=addPath&&addPath.newPos+1=newLen&&oldLen<=_oldPos+1)return done(buildValues(self,basePath.components,newString,oldString,self.useLongestToken));bestPath[diagonalPath]=basePath}else bestPath[diagonalPath]=void 0}var path;editLength++}if(callback)!function exec(){setTimeout(function(){if(maxEditLength=diff.length-2&&lines.length<=options.context){var oldEOFNewline=/\n$/.test(oldStr),newEOFNewline=/\n$/.test(newStr),noNlBeforeAdds=0==lines.length&&curRange.length>hunk.oldLines;!oldEOFNewline&&noNlBeforeAdds&&curRange.splice(hunk.oldLines,0,"\\ No newline at end of file"),(oldEOFNewline||noNlBeforeAdds)&&newEOFNewline||curRange.push("\\ No newline at end of file")}hunks.push(hunk),newRangeStart=oldRangeStart=0,curRange=[]}oldLine+=lines.length,newLine+=lines.length}},i=0;iarray.length)return!1;for(var i=0;i/g,">")).replace(/"/g,""")}arrayDiff.tokenize=function(value){return value.slice()},arrayDiff.join=arrayDiff.removeEmpty=function(value){return value},exports.Diff=Diff,exports.diffChars=function(oldStr,newStr,options){return characterDiff.diff(oldStr,newStr,options)},exports.diffWords=function(oldStr,newStr,options){return options=generateOptions(options,{ignoreWhitespace:!0}),wordDiff.diff(oldStr,newStr,options)},exports.diffWordsWithSpace=function(oldStr,newStr,options){return wordDiff.diff(oldStr,newStr,options)},exports.diffLines=diffLines,exports.diffTrimmedLines=function(oldStr,newStr,callback){var options=generateOptions(callback,{ignoreWhitespace:!0});return lineDiff.diff(oldStr,newStr,options)},exports.diffSentences=function(oldStr,newStr,callback){return sentenceDiff.diff(oldStr,newStr,callback)},exports.diffCss=function(oldStr,newStr,callback){return cssDiff.diff(oldStr,newStr,callback)},exports.diffJson=function(oldObj,newObj,options){return jsonDiff.diff(oldObj,newObj,options)},exports.diffArrays=function(oldArr,newArr,callback){return arrayDiff.diff(oldArr,newArr,callback)},exports.structuredPatch=structuredPatch,exports.createTwoFilesPatch=createTwoFilesPatch,exports.createPatch=function(fileName,oldStr,newStr,oldHeader,newHeader,options){return createTwoFilesPatch(fileName,fileName,oldStr,newStr,oldHeader,newHeader,options)},exports.applyPatch=applyPatch,exports.applyPatches=function(uniDiff,options){"string"==typeof uniDiff&&(uniDiff=parsePatch(uniDiff));var currentIndex=0;!function processIndex(){var index=uniDiff[currentIndex++];if(!index)return options.complete();options.loadFile(index,function(err,data){if(err)return options.complete(err);var updatedContent=applyPatch(data,index,options);options.patched(index,updatedContent,function(err){if(err)return options.complete(err);processIndex()})})}()},exports.parsePatch=parsePatch,exports.merge=function(mine,theirs,base){mine=loadPatch(mine,base),theirs=loadPatch(theirs,base);var ret={};(mine.index||theirs.index)&&(ret.index=mine.index||theirs.index),(mine.newFileName||theirs.newFileName)&&(fileNameChanged(mine)?fileNameChanged(theirs)?(ret.oldFileName=selectField(ret,mine.oldFileName,theirs.oldFileName),ret.newFileName=selectField(ret,mine.newFileName,theirs.newFileName),ret.oldHeader=selectField(ret,mine.oldHeader,theirs.oldHeader),ret.newHeader=selectField(ret,mine.newHeader,theirs.newHeader)):(ret.oldFileName=mine.oldFileName,ret.newFileName=mine.newFileName,ret.oldHeader=mine.oldHeader,ret.newHeader=mine.newHeader):(ret.oldFileName=theirs.oldFileName||mine.oldFileName,ret.newFileName=theirs.newFileName||mine.newFileName,ret.oldHeader=theirs.oldHeader||mine.oldHeader,ret.newHeader=theirs.newHeader||mine.newHeader)),ret.hunks=[];for(var mineIndex=0,theirsIndex=0,mineOffset=0,theirsOffset=0;mineIndex"):change.removed&&ret.push(""),ret.push(escapeHTML(change.value)),change.added?ret.push(""):change.removed&&ret.push("")}return ret.join("")},exports.canonicalize=canonicalize,Object.defineProperty(exports,"__esModule",{value:!0})},"object"==typeof exports&&void 0!==module?factory(exports):"function"==typeof define&&define.amd?define(["exports"],factory):factory((global=global||self).Diff={})},{}],3:[function(require,module,exports){!function(Hogan){var rIsWhitespace=/\S/,rQuot=/\"/g,rNewline=/\n/g,rCr=/\r/g,rSlash=/\\/g,rLineSep=/\u2028/,rParagraphSep=/\u2029/;function cleanTripleStache(token){"}"===token.n.substr(token.n.length-1)&&(token.n=token.n.substring(0,token.n.length-1))}function trim(s){return s.trim?s.trim():s.replace(/^\s*|\s*$/g,"")}function tagChange(tag,text,index){if(text.charAt(index)!=tag.charAt(0))return!1;for(var i=1,l=tag.length;i":7,"=":8,_v:9,"{":10,"&":11,_t:12},Hogan.scan=function(text,delimiters){var len=text.length,state=0,tagType=null,tag=null,buf="",tokens=[],seenTag=!1,i=0,lineStart=0,otag="{{",ctag="}}";function addBuf(){0"==next.tag&&(next.indent=tokens[j].text.toString()),tokens.splice(j,1));else noNewLine||tokens.push({tag:"\n"});seenTag=!1,lineStart=tokens.length}function changeDelimiters(text,index){var close="="+ctag,closeIndex=text.indexOf(close,index),delimiters=trim(text.substring(text.indexOf("=",index)+1,closeIndex)).split(" ");return otag=delimiters[0],ctag=delimiters[delimiters.length-1],closeIndex+close.length-1}for(delimiters&&(delimiters=delimiters.split(" "),otag=delimiters[0],ctag=delimiters[1]),i=0;i":createPartial,"<":function(node,context){var ctx={partials:{},code:"",subs:{},inPartial:!0};Hogan.walk(node.nodes,ctx);var template=context.partials[createPartial(node,context)];template.subs=ctx.subs,template.partials=ctx.partials},$:function(node,context){var ctx={subs:{},code:"",partials:context.partials,prefix:node.n};Hogan.walk(node.nodes,ctx),context.subs[node.n]=ctx.code,context.inPartial||(context.code+='t.sub("'+esc(node.n)+'",c,p,i);')},"\n":function(node,context){context.code+=write('"\\n"'+(node.last?"":" + i"))},_v:function(node,context){context.code+="t.b(t.v(t."+chooseMethod(node.n)+'("'+esc(node.n)+'",c,p,0)));'},_t:function(node,context){context.code+=write('"'+esc(node.text)+'"')},"{":tripleStache,"&":tripleStache},Hogan.walk=function(nodelist,context){for(var func,i=0,l=nodelist.length;i/g,rApos=/\'/g,rQuot=/\"/g,hChars=/[&<>\"\']/;function coerceToString(val){return String(null==val?"":val)}var isArray=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)}}(void 0!==exports?exports:{})},{}],6:[function(require,module,exports){function merge_recursive(base,extend){if("object"!==typeOf(base))return extend;for(var key in extend)"object"===typeOf(base[key])&&"object"===typeOf(extend[key])?base[key]=merge_recursive(base[key],extend[key]):base[key]=extend[key];return base}function merge(clone,recursive,argv){var result=argv[0],size=argv.length;!clone&&"object"===typeOf(result)||(result={});for(var index=0;indexconfig.maxLineLengthHighlight||unprefixedLine2.length>config.maxLineLengthHighlight)return{first:{prefix:linePrefix1,line:utils.escape(unprefixedLine1)},second:{prefix:linePrefix2,line:utils.escape(unprefixedLine2)}};diff=config.charByChar?jsDiff.diffChars(unprefixedLine1,unprefixedLine2):jsDiff.diffWordsWithSpace(unprefixedLine1,unprefixedLine2);var highlightedLine="",changedWords=[];if(!config.charByChar&&"words"===config.matching){var treshold=.25;void 0!==config.matchWordsThreshold&&(treshold=config.matchWordsThreshold);var matcher=Rematch.rematch(function(a,b){var amod=a.value,bmod=b.value;return Rematch.distance(amod,bmod)}),removed=diff.filter(function(element){return element.removed});matcher(diff.filter(function(element){return element.added}),removed).forEach(function(chunk){1===chunk[0].length&&1===chunk[1].length&&Rematch.distance(chunk[0][0].value,chunk[1][0].value)"+escapedValue+"":escapedValue}),{first:{prefix:linePrefix1,line:function(line){return line.replace(/(]*>((.|\n)*?)<\/ins>)/g,"")}(highlightedLine)},second:{prefix:linePrefix2,line:function(line){return line.replace(/(]*>((.|\n)*?)<\/del>)/g,"")}(highlightedLine)}}},module.exports.PrinterUtils=new PrinterUtils},{"./rematch.js":16,"./utils.js":19,diff:2}],16:[function(require,module,exports){function levenshtein(a,b){if(0===a.length)return b.length;if(0===b.length)return a.length;var i,j,matrix=[];for(i=0;i<=b.length;i++)matrix[i]=[i];for(j=0;j<=a.length;j++)matrix[0][j]=j;for(i=1;i<=b.length;i++)for(j=1;j<=a.length;j++)b.charAt(i-1)===a.charAt(j-1)?matrix[i][j]=matrix[i-1][j-1]:matrix[i][j]=Math.min(matrix[i-1][j-1]+1,Math.min(matrix[i][j-1]+1,matrix[i-1][j]+1));return matrix[b.length][a.length]}var Rematch;(Rematch={}).levenshtein=levenshtein,Rematch.distance=function(x,y){return levenshtein(x=x.trim(),y=y.trim())/(x.length+y.length)},Rematch.rematch=function(distanceFunction){return function group(a,b,level,cache){void 0===cache&&(cache={});var bm=function(a,b,cache){for(var bestMatch,bestMatchDist=1/0,i=0;itailA||b.length>tailB)&&(result=result.concat(group2)),result}},module.exports.Rematch=Rematch},{}],17:[function(require,module,exports){function SideBySidePrinter(config){this.config=config;var HoganJsUtils=require("./hoganjs-utils.js").HoganJsUtils;hoganUtils=new HoganJsUtils(config)}var hoganUtils,diffParser,printerUtils,utils,Rematch,matcher;diffParser=require("./diff-parser.js").DiffParser,printerUtils=require("./printer-utils.js").PrinterUtils,utils=require("./utils.js").Utils,Rematch=require("./rematch.js").Rematch,matcher=Rematch.rematch(function(a,b){var amod=a.content.substr(1),bmod=b.content.substr(1);return Rematch.distance(amod,bmod)}),SideBySidePrinter.prototype.makeDiffHtml=function(file,diffs){var fileDiffTemplate=hoganUtils.template("side-by-side","file-diff"),filePathTemplate=hoganUtils.template("generic","file-path"),fileIconTemplate=hoganUtils.template("icon","file"),fileTagTemplate=hoganUtils.template("tag",printerUtils.getFileTypeIcon(file));return fileDiffTemplate.render({file:file,fileHtmlId:printerUtils.getHtmlId(file),diffs:diffs,filePath:filePathTemplate.render({fileDiffName:printerUtils.getDiffName(file)},{fileIcon:fileIconTemplate,fileTag:fileTagTemplate})})},SideBySidePrinter.prototype.generateSideBySideJsonHtml=function(diffFiles){var that=this,content=diffFiles.map(function(file){var diffs;return diffs=file.blocks.length?that.generateSideBySideFileHtml(file):that.generateEmptyDiff(),that.makeDiffHtml(file,diffs)}).join("\n");return hoganUtils.render("generic","wrapper",{content:content})},SideBySidePrinter.prototype.makeSideHtml=function(blockHeader){return hoganUtils.render("generic","column-line-number",{diffParser:diffParser,blockHeader:utils.escape(blockHeader),lineClass:"d2h-code-side-linenumber",contentClass:"d2h-code-side-line"})},SideBySidePrinter.prototype.generateSideBySideFileHtml=function(file){var that=this,fileHtml={left:"",right:""};return file.blocks.forEach(function(block){fileHtml.left+=that.makeSideHtml(block.header),fileHtml.right+=that.makeSideHtml("");var oldLines=[],newLines=[];function processChangeBlock(){var matches,insertType,deleteType,comparisons=oldLines.length*newLines.length,maxLineSizeInBlock=Math.max.apply(null,oldLines.concat(newLines).map(function(elem){return elem.length})),doMatching=comparisons'),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(t.rp("'),t.b(t.v(t.f("fileName",c,p,0))),t.b(""),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(' '),t.b(t.v(t.f("addedLines",c,p,0))),t.b(""),t.b("\n"+i),t.b(' '),t.b(t.v(t.f("deletedLines",c,p,0))),t.b(""),t.b("\n"+i),t.b(" "),t.b("\n"+i),t.b(" "),t.b("\n"+i),t.b(""),t.fl()},partials:{"'),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b(' Files changed ('),t.b(t.v(t.f("filesNumber",c,p,0))),t.b(")"),t.b("\n"+i),t.b(' hide'),t.b("\n"+i),t.b(' show'),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b('
    '),t.b("\n"+i),t.b(" "),t.b(t.t(t.f("files",c,p,0))),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b(""),t.fl()},partials:{},subs:{}}),global.browserTemplates["generic-column-line-number"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b(""),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b('
'),t.b(t.t(t.f("blockHeader",c,p,0))),t.b("
"),t.b("\n"+i),t.b(" "),t.b("\n"+i),t.b(""),t.fl()},partials:{},subs:{}}),global.browserTemplates["generic-empty-diff"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b(""),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b(" File without changes"),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b(" "),t.b("\n"+i),t.b(""),t.fl()},partials:{},subs:{}}),global.browserTemplates["generic-file-path"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b(''),t.b("\n"+i),t.b(t.rp("'),t.b(t.v(t.f("fileDiffName",c,p,0))),t.b(""),t.b("\n"+i),t.b(t.rp(""),t.fl()},partials:{""),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(" "),t.b(t.t(t.f("lineNumber",c,p,0))),t.b("\n"+i),t.b(" "),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.s(t.f("prefix",c,p,1),c,p,0,171,247,"{{ }}")&&(t.rs(c,p,function(c,p,t){t.b(' '),t.b(t.t(t.f("prefix",c,p,0))),t.b(""),t.b("\n"+i)}),c.pop()),t.s(t.f("content",c,p,1),c,p,0,279,353,"{{ }}")&&(t.rs(c,p,function(c,p,t){t.b(' '),t.b(t.t(t.f("content",c,p,0))),t.b(""),t.b("\n"+i)}),c.pop()),t.b("
"),t.b("\n"+i),t.b(" "),t.b("\n"+i),t.b(""),t.fl()},partials:{},subs:{}}),global.browserTemplates["generic-wrapper"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('
'),t.b("\n"+i),t.b(" "),t.b(t.t(t.f("content",c,p,0))),t.b("\n"+i),t.b("
"),t.fl()},partials:{},subs:{}}),global.browserTemplates["icon-file-added"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('"),t.fl()},partials:{},subs:{}}),global.browserTemplates["icon-file-changed"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('"),t.fl()},partials:{},subs:{}}),global.browserTemplates["icon-file-deleted"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('"),t.fl()},partials:{},subs:{}}),global.browserTemplates["icon-file-renamed"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('"),t.fl()},partials:{},subs:{}}),global.browserTemplates["icon-file"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('"),t.fl()},partials:{},subs:{}}),global.browserTemplates["line-by-line-file-diff"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('
'),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b(" "),t.b(t.t(t.f("filePath",c,p,0))),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(" "),t.b(t.t(t.f("diffs",c,p,0))),t.b("\n"+i),t.b(" "),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b("
"),t.fl()},partials:{},subs:{}}),global.browserTemplates["line-by-line-numbers"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('
'),t.b(t.v(t.f("oldNumber",c,p,0))),t.b("
"),t.b("\n"+i),t.b('
'),t.b(t.v(t.f("newNumber",c,p,0))),t.b("
"),t.fl()},partials:{},subs:{}}),global.browserTemplates["side-by-side-file-diff"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('
'),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b(" "),t.b(t.t(t.f("filePath",c,p,0))),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(" "),t.b(t.t(t.d("diffs.left",c,p,0))),t.b("\n"+i),t.b(" "),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b('
'),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(' '),t.b("\n"+i),t.b(" "),t.b(t.t(t.d("diffs.right",c,p,0))),t.b("\n"+i),t.b(" "),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b("
"),t.b("\n"+i),t.b("
"),t.fl()},partials:{},subs:{}}),global.browserTemplates["tag-file-added"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('ADDED'),t.fl()},partials:{},subs:{}}),global.browserTemplates["tag-file-changed"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('CHANGED'),t.fl()},partials:{},subs:{}}),global.browserTemplates["tag-file-deleted"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('DELETED'),t.fl()},partials:{},subs:{}}),global.browserTemplates["tag-file-renamed"]=new Hogan.Template({code:function(c,p,i){var t=this;return t.b(i=i||""),t.b('RENAMED'),t.fl()},partials:{},subs:{}}),module.exports=global.browserTemplates}()}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"hogan.js":4}],19:[function(require,module,exports){function Utils(){}var merge;merge=require("merge"),Utils.prototype.escape=function(str){return str.slice(0).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")},Utils.prototype.startsWith=function(str,start){if("object"!=typeof start)return str&&0===str.indexOf(start);var result=!1;return start.forEach(function(s){0===str.indexOf(s)&&(result=!0)}),result},Utils.prototype.valueOrEmpty=function(value){return value||""},Utils.prototype.safeConfig=function(cfg,defaultConfig){return merge.recursive(!0,defaultConfig,cfg)},module.exports.Utils=new Utils},{merge:6}]},{},[10]); \ No newline at end of file diff --git a/diff/src/main/assets/index.html b/diff/src/main/assets/index.html deleted file mode 100644 index d24b47fc..00000000 --- a/diff/src/main/assets/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/diff/src/main/java/com/fastaccess/fasthub/diff/CommitLineBuilder.kt b/diff/src/main/java/com/fastaccess/fasthub/diff/CommitLineBuilder.kt new file mode 100644 index 00000000..27f2376c --- /dev/null +++ b/diff/src/main/java/com/fastaccess/fasthub/diff/CommitLineBuilder.kt @@ -0,0 +1,74 @@ +package com.fastaccess.fasthub.diff + +import com.fastaccess.data.model.CommitLinesModel +import com.fastaccess.data.model.CommitLinesModel.Companion.ADDITION +import com.fastaccess.data.model.CommitLinesModel.Companion.DELETION +import com.fastaccess.data.model.CommitLinesModel.Companion.PATCH +import com.fastaccess.data.model.CommitLinesModel.Companion.TRANSPARENT +import java.util.* +import java.util.regex.Pattern +import kotlin.math.abs + +object CommitLineBuilder { + private val HUNK_TITLE = Pattern.compile("^.*-([0-9]+)(?:,([0-9]+))? \\+([0-9]+)(?:,([0-9]+))?.*$") + fun buildLines(patch: String?): List { + val models = ArrayList() + if (!patch.isNullOrEmpty()) { + val split = patch.split("\\r?\\n|\\r".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + if (split.size > 1) { + var leftLineNo = -1 + var rightLineNo = -1 + var position = 0 + for (text in split) { + var _text: String = text + val firstChar = _text[0] + var addLeft = false + var addRight = false + var color = TRANSPARENT + if (_text.startsWith("@@")) { + color = PATCH + val matcher = HUNK_TITLE.matcher(_text.trim { it <= ' ' }) + if (matcher.matches()) { + try { + leftLineNo = abs(matcher.group(1)?.toIntOrNull() ?: 0) - 1 + rightLineNo = (matcher.group(3)?.toIntOrNull() ?: 0) - 1 + } catch (e: NumberFormatException) { + e.printStackTrace() + } + + } + } else if (firstChar == '+') { + position++ + color = ADDITION + ++rightLineNo + addRight = true + addLeft = false + } else if (firstChar == '-') { + position++ + color = DELETION + ++leftLineNo + addRight = false + addLeft = true + } else { + position++ + addLeft = true + addRight = true + ++rightLineNo + ++leftLineNo + } + val index = _text.indexOf("\\ No newline at end of file") + if (index != -1) { + _text = _text.replace("\\ No newline at end of file", "") + } + models.add( + CommitLinesModel( + _text.replace("\t", ""), color, if (_text.startsWith("@@") || !addLeft) -1 else leftLineNo, + if (_text.startsWith("@@") || !addRight) -1 else rightLineNo, index != -1, position, false + ) + ) + } + } + } + return models + } +} \ No newline at end of file diff --git a/diff/src/main/java/com/fastaccess/fasthub/diff/DiffViewerActivity.kt b/diff/src/main/java/com/fastaccess/fasthub/diff/DiffViewerActivity.kt index 05749502..d9dfda7d 100644 --- a/diff/src/main/java/com/fastaccess/fasthub/diff/DiffViewerActivity.kt +++ b/diff/src/main/java/com/fastaccess/fasthub/diff/DiffViewerActivity.kt @@ -5,13 +5,28 @@ import android.content.Intent import android.os.Bundle import android.widget.TextView import androidx.appcompat.widget.Toolbar +import com.fastaccess.data.model.CommitLinesModel +import com.fastaccess.data.repository.SchedulerProvider import com.fastaccess.fasthub.dagger.annotations.ForActivity +import com.fastaccess.fasthub.diff.adapter.CommitLinesAdapter import com.fastaccess.github.base.BaseActivity import com.fastaccess.github.base.utils.EXTRA +import io.reactivex.Observable +import io.reactivex.disposables.Disposable import kotlinx.android.synthetic.main.diff_patch_viewer_layout.* +import javax.inject.Inject class DiffViewerActivity : BaseActivity() { + @Inject lateinit var schedulerProvider: SchedulerProvider + + private var disposable: Disposable? = null + private val adapter by lazy { + CommitLinesAdapter { + //TODO + } + } + override fun layoutRes(): Int = R.layout.diff_patch_viewer_layout override fun onActivityCreatedWithUser(savedInstanceState: Bundle?) { @@ -22,11 +37,30 @@ class DiffViewerActivity : BaseActivity() { setNavigationIcon(R.drawable.ic_clear) setSupportActionBar(this) } - intent?.getStringExtra(EXTRA)?.let { - webview.loadDiff(it) + diffRecyclerView.adapter = adapter + intent?.getStringExtra(EXTRA)?.let { patch -> + val observable = Observable.fromPublisher> { s -> + runCatching { CommitLineBuilder.buildLines(patch) } + .onSuccess { s.onNext(it) } + .onFailure { s.onError(it) } + s.onComplete() + } + disposable = observable.subscribeOn(schedulerProvider.ioThread()) + .observeOn(schedulerProvider.uiThread()) + .subscribe({ + adapter.submitList(it) + }, { + it.printStackTrace() + finish() + }) } ?: run { finish() } } + override fun onDestroy() { + disposable?.dispose() + super.onDestroy() + } + companion object { fun startActivity(@ForActivity context: Context, patch: String) { context.startActivity(Intent(context, DiffViewerActivity::class.java).apply { diff --git a/diff/src/main/java/com/fastaccess/fasthub/diff/DiffWebView.kt b/diff/src/main/java/com/fastaccess/fasthub/diff/DiffWebView.kt deleted file mode 100644 index 859cb364..00000000 --- a/diff/src/main/java/com/fastaccess/fasthub/diff/DiffWebView.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.fastaccess.fasthub.diff - -import android.annotation.SuppressLint -import android.content.Context -import android.util.AttributeSet -import android.webkit.WebChromeClient -import android.webkit.WebView -import androidx.webkit.WebViewClientCompat -import timber.log.Timber - - -class DiffWebView : WebView { - constructor(context: Context?) : super(context) - constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - - @SuppressLint("SetJavaScriptEnabled") - fun loadDiff(diff: String) { - settings.apply { - javaScriptEnabled = true - defaultTextEncodingName = "utf-8" - webChromeClient = WebChromeClient() - } - post { - webViewClient = object : WebViewClientCompat() { - override fun onPageFinished(view: WebView?, url: String?) { - super.onPageFinished(view, url) - Timber.e("here!") - loadUrl("javascript:loadDiff('$diff')") - } - } - loadUrl("file:///android_asset/index.html") - } - } -} \ No newline at end of file diff --git a/diff/src/main/java/com/fastaccess/fasthub/diff/adapter/CommitLinesAdapter.kt b/diff/src/main/java/com/fastaccess/fasthub/diff/adapter/CommitLinesAdapter.kt new file mode 100644 index 00000000..fcd28330 --- /dev/null +++ b/diff/src/main/java/com/fastaccess/fasthub/diff/adapter/CommitLinesAdapter.kt @@ -0,0 +1,59 @@ +package com.fastaccess.fasthub.diff.adapter + +import android.graphics.Color +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import com.fastaccess.data.model.CommitLinesModel +import com.fastaccess.fasthub.diff.R +import com.fastaccess.github.base.adapter.BaseViewHolder +import com.fastaccess.github.extensions.getColorAttr +import com.fastaccess.github.extensions.getDrawableCompat +import com.fastaccess.markdown.widget.SpannableBuilder +import kotlinx.android.synthetic.main.commit_line_row_item.view.* + +class CommitLinesAdapter( + private val callback: (CommitLinesModel) -> Unit +) : ListAdapter(object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: CommitLinesModel, newItem: CommitLinesModel): Boolean = oldItem.position == newItem.position + override fun areContentsTheSame(oldItem: CommitLinesModel, newItem: CommitLinesModel): Boolean = oldItem == newItem +}) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = CommitLineViewHolder(parent).apply { + itemView.setOnClickListener { getItem(adapterPosition)?.let(callback) } + } + + override fun onBindViewHolder(holder: CommitLineViewHolder, position: Int) = holder.bind(getItem(position)) + +} + +class CommitLineViewHolder(parent: ViewGroup) : BaseViewHolder( + LayoutInflater.from(parent.context).inflate(R.layout.commit_line_row_item, parent, false) +) { + override fun bind(item: CommitLinesModel) { + itemView.apply { + leftLinNo.text = if (item.leftLineNo > 0) "${item.leftLineNo}" else " " + rightLinNo.text = if (item.rightLineNo > 0) "${item.rightLineNo}" else " " + hasComment.isVisible = item.hasCommentedOn + when (item.color) { + CommitLinesModel.ADDITION -> textView.setBackgroundColor(context.getColorAttr(R.attr.patch_addition)) + CommitLinesModel.DELETION -> textView.setBackgroundColor(context.getColorAttr(R.attr.patch_deletion)) + CommitLinesModel.PATCH -> { + leftLinNo.visibility = View.GONE + rightLinNo.visibility = View.GONE + textView.setBackgroundColor(context.getColorAttr(R.attr.patch_ref)) + } + else -> textView.setBackgroundColor(Color.TRANSPARENT) + } + if (item.noNewLine) { + textView.text = SpannableBuilder.builder().append(item.text).append(" ") + .append(context.getDrawableCompat(R.drawable.ic_newline)) + } else { + textView.setText(item.text) + } + } + } +} \ No newline at end of file diff --git a/diff/src/main/res/layout/commit_line_row_item.xml b/diff/src/main/res/layout/commit_line_row_item.xml new file mode 100644 index 00000000..cdf03440 --- /dev/null +++ b/diff/src/main/res/layout/commit_line_row_item.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/diff/src/main/res/layout/diff_patch_viewer_layout.xml b/diff/src/main/res/layout/diff_patch_viewer_layout.xml index 861a9b24..1e1805ec 100644 --- a/diff/src/main/res/layout/diff_patch_viewer_layout.xml +++ b/diff/src/main/res/layout/diff_patch_viewer_layout.xml @@ -1,12 +1,13 @@ - - + android:layout_height="wrap_content" + android:paddingStart="@dimen/spacing_xs_large" + android:paddingEnd="@dimen/spacing_xs_large" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + tools:itemCount="40" + tools:listitem="@layout/commit_line_row_item" /> \ No newline at end of file diff --git a/domain/src/main/java/com/fastaccess/domain/services/CommitService.kt b/domain/src/main/java/com/fastaccess/domain/services/CommitService.kt index 75886962..b2e2cd7e 100644 --- a/domain/src/main/java/com/fastaccess/domain/services/CommitService.kt +++ b/domain/src/main/java/com/fastaccess/domain/services/CommitService.kt @@ -3,6 +3,7 @@ package com.fastaccess.domain.services import com.fastaccess.domain.response.CommentResponse import com.fastaccess.domain.response.CommitFilesResponseModel import com.fastaccess.domain.response.body.CommentRequestModel +import io.reactivex.Maybe import io.reactivex.Observable import retrofit2.Response import retrofit2.http.* @@ -15,6 +16,13 @@ interface CommitService { @Path("sha") ref: String ): Observable + @Headers("Accept: application/vnd.github.v3.diff") + @GET("repos/{owner}/{repo}/commits/{sha}") fun getCommitDiff( + @Path("owner") owner: String, + @Path("repo") repo: String, + @Path("sha") ref: String + ): Maybe + @POST("repos/{owner}/{repo}/commits/{sha}/comments") fun postCommitComment( @Path("owner") owner: String, @Path("repo") repo: String,