diff --git a/app/build.gradle b/app/build.gradle index 20421d7f..4e94660d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -129,6 +129,7 @@ dependencies { implementation project(':markdown') implementation project(':editor') implementation project(':commits') + implementation project(':diff') implementation dependency.kotlin implementation dependency.supportLibraries implementation dependency.extrasLibraries diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c9193a90..f46e2baa 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -138,6 +138,10 @@ android:name="com.fastaccess.fasthub.commit.list.CommitsListActivity" android:parentActivityName=".ui.modules.main.MainActivity" /> + + @@ -123,7 +124,8 @@ class AuthLoginFragment : com.fastaccess.github.base.BaseFragment() { viewModel.loggedInUser.observe(this, Observer { model -> if (model != null) { addDisposal(viewModel.clearDb() - .subscribe({ callback?.onUserLoggedIn(model) }, { throwable -> view?.let { showSnackBar(it, message = throwable.message) } })) + .subscribe({ callback?.onUserLoggedIn(model) }, { throwable -> view?.let { showSnackBar(it, message = throwable.message) } }) + ) } else { view?.let { showSnackBar(it, resId = R.string.failed_login) } } @@ -134,10 +136,6 @@ class AuthLoginFragment : com.fastaccess.github.base.BaseFragment() { const val TAG = "AuthLoginFragment" fun newInstance(accessToken: Boolean = false, isEnterprise: Boolean = false): AuthLoginFragment = AuthLoginFragment() .apply { - val enter = Slide(Gravity.END) - val exit = Slide(Gravity.START) - enterTransition = enter - exitTransition = exit arguments = Bundle().apply { putBoolean(EXTRA, accessToken) putBoolean(EXTRA_TWO, isEnterprise) diff --git a/build.gradle b/build.gradle index 2e6adc1f..4d1f3d71 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,9 @@ configurations { ktlint } -buildscript { +buildscript { + ext.kotlin_version = '1.3.50' + ext { kotlin = '1.3.50' kotlin_version = '1.3.50' @@ -27,7 +29,7 @@ buildscript { classpath 'com.apollographql.apollo:apollo-gradle-plugin:1.0.1' classpath 'gradle.plugin.org.jlleitschuh.gradle:ktlint-gradle:2.3.0' classpath "com.github.ben-manes:gradle-versions-plugin:0.21.0" - } + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { @@ -47,4 +49,4 @@ task clean(type: Delete) { subprojects { apply plugin: "org.jlleitschuh.gradle.ktlint" -} \ No newline at end of file +} diff --git a/commits/build.gradle b/commits/build.gradle index c7c75842..d0cb00fc 100644 --- a/commits/build.gradle +++ b/commits/build.gradle @@ -53,6 +53,7 @@ dependencies { implementation project(':editor') implementation project(':dagger') implementation project(':reactions') + implementation project(':diff') implementation dependency.kotlin implementation dependency.supportLibraries implementation dependency.extrasLibraries diff --git a/commits/src/main/java/com/fastaccess/fasthub/commit/view/files/CommitFilesFragment.kt b/commits/src/main/java/com/fastaccess/fasthub/commit/view/files/CommitFilesFragment.kt index 5fe931a3..f82a53c0 100644 --- a/commits/src/main/java/com/fastaccess/fasthub/commit/view/files/CommitFilesFragment.kt +++ b/commits/src/main/java/com/fastaccess/fasthub/commit/view/files/CommitFilesFragment.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModelProvider import com.fastaccess.data.model.FragmentType import com.fastaccess.fasthub.commit.R import com.fastaccess.fasthub.commit.adapter.CommitFilesAdapter +import com.fastaccess.fasthub.diff.DiffViewerActivity import com.fastaccess.github.base.BaseFragment import com.fastaccess.github.base.BaseViewModel import com.fastaccess.github.base.extensions.isConnected @@ -27,7 +28,7 @@ class CommitFilesFragment : BaseFragment() { private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(CommitFilesViewModel::class.java) } private val adapter by lazy { CommitFilesAdapter { position, commitFilesModel -> - // TODO(open file) + DiffViewerActivity.startActivity(requireContext(), commitFilesModel.patch ?: "") } } diff --git a/diff/.gitignore b/diff/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/diff/.gitignore @@ -0,0 +1 @@ +/build diff --git a/diff/build.gradle b/diff/build.gradle new file mode 100644 index 00000000..183eed5d --- /dev/null +++ b/diff/build.gradle @@ -0,0 +1,64 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' +apply plugin: 'kotlin-android-extensions' + +android { + def conf = rootProject.ext.android + + compileSdkVersion conf.compileSdkVersion + + defaultConfig { + minSdkVersion conf.minSdkVersion + targetSdkVersion conf.targetSdkVersion + versionCode conf.versionCode + versionName conf.versionName + multiDexEnabled + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + javaCompileOptions { + annotationProcessorOptions { + includeCompileClasspath = true + } + } + } + + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + def dependency = rootProject.ext + + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation project(':base') + implementation project(':data') + implementation project(':domain') + implementation project(':resources') + implementation project(':extensions') + implementation project(':dagger') + implementation dependency.kotlin + implementation dependency.supportLibraries + implementation dependency.extrasLibraries + implementation dependency.networking + implementation dependency.rxJava + implementation dependency.extrasLibraries + implementation dependency.dagger + implementation dependency.archs + + kapt dependency.processing + +} diff --git a/diff/consumer-rules.pro b/diff/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/diff/proguard-rules.pro b/diff/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/diff/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/diff/src/main/AndroidManifest.xml b/diff/src/main/AndroidManifest.xml new file mode 100644 index 00000000..4182afc6 --- /dev/null +++ b/diff/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/diff/src/main/assets/diff.js b/diff/src/main/assets/diff.js new file mode 100644 index 00000000..80e1c734 --- /dev/null +++ b/diff/src/main/assets/diff.js @@ -0,0 +1,10 @@ +function loadDiff(diff) { + var diffHtml = Diff2Html.getPrettyHtml(diff, { + inputFormat: 'diff', + showFiles: true, + matching: 'lines', + 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 new file mode 100644 index 00000000..7d22dd4a --- /dev/null +++ b/diff/src/main/assets/diff2html.css @@ -0,0 +1,365 @@ +/* + * + * 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 new file mode 100644 index 00000000..be3ff536 --- /dev/null +++ b/diff/src/main/assets/diff2html.min.js @@ -0,0 +1 @@ +!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 new file mode 100644 index 00000000..d24b47fc --- /dev/null +++ b/diff/src/main/assets/index.html @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ 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 new file mode 100644 index 00000000..05749502 --- /dev/null +++ b/diff/src/main/java/com/fastaccess/fasthub/diff/DiffViewerActivity.kt @@ -0,0 +1,37 @@ +package com.fastaccess.fasthub.diff + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.widget.TextView +import androidx.appcompat.widget.Toolbar +import com.fastaccess.fasthub.dagger.annotations.ForActivity +import com.fastaccess.github.base.BaseActivity +import com.fastaccess.github.base.utils.EXTRA +import kotlinx.android.synthetic.main.diff_patch_viewer_layout.* + +class DiffViewerActivity : BaseActivity() { + + override fun layoutRes(): Int = R.layout.diff_patch_viewer_layout + + override fun onActivityCreatedWithUser(savedInstanceState: Bundle?) { + title = "" + findViewById(R.id.toolbar).apply { + title = "" + findViewById(R.id.toolbarTitle).text = getString(R.string.commit) + setNavigationIcon(R.drawable.ic_clear) + setSupportActionBar(this) + } + intent?.getStringExtra(EXTRA)?.let { + webview.loadDiff(it) + } ?: run { finish() } + } + + companion object { + fun startActivity(@ForActivity context: Context, patch: String) { + context.startActivity(Intent(context, DiffViewerActivity::class.java).apply { + putExtra(EXTRA, patch) + }) + } + } +} \ No newline at end of file diff --git a/diff/src/main/java/com/fastaccess/fasthub/diff/DiffWebView.kt b/diff/src/main/java/com/fastaccess/fasthub/diff/DiffWebView.kt new file mode 100644 index 00000000..859cb364 --- /dev/null +++ b/diff/src/main/java/com/fastaccess/fasthub/diff/DiffWebView.kt @@ -0,0 +1,35 @@ +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/res/layout/diff_patch_viewer_layout.xml b/diff/src/main/res/layout/diff_patch_viewer_layout.xml new file mode 100644 index 00000000..861a9b24 --- /dev/null +++ b/diff/src/main/res/layout/diff_patch_viewer_layout.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 867fbde7..efac2040 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ -include ':app', ':data', ':domain', ':resources', ':extensions', ':markdown', ':editor' +include ':app', ':data', ':domain', ':resources', ':extensions', ':markdown', ':editor', ':diff' include ':commits' include ':base' include ':dagger'