diff --git a/app/build.gradle b/app/build.gradle index 30a9a46..65a65e5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -110,6 +110,7 @@ android { // Split resources. // https://medium.com/google-developer-experts/android-project-structure-alternative-way-29ce766682f0#.sjnhetuhb res.srcDirs = [ + 'src/main/res/browser', 'src/main/res/common', 'src/main/res/home' ] diff --git a/app/src/main/assets/browser.html b/app/src/main/assets/browser.html deleted file mode 100644 index b7d329c..0000000 --- a/app/src/main/assets/browser.html +++ /dev/null @@ -1,40 +0,0 @@ - - -
- - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/java/com/mercandalli/android/browser/browser/BrowserActivity.kt b/app/src/main/java/com/mercandalli/android/browser/browser/BrowserActivity.kt index d27505f..dedeb3d 100644 --- a/app/src/main/java/com/mercandalli/android/browser/browser/BrowserActivity.kt +++ b/app/src/main/java/com/mercandalli/android/browser/browser/BrowserActivity.kt @@ -9,6 +9,8 @@ import android.os.Bundle import android.support.design.widget.AppBarLayout import android.support.v4.content.ContextCompat import android.support.v7.app.AppCompatActivity +import android.support.v7.widget.PopupMenu +import android.view.Gravity import android.view.KeyEvent import android.view.View import android.view.View.GONE @@ -16,6 +18,7 @@ import android.view.View.VISIBLE import android.widget.EditText import android.widget.ProgressBar import android.widget.TextView +import android.widget.Toast import com.mercandalli.android.browser.R import com.mercandalli.android.browser.keyboard.KeyboardUtils import com.mercandalli.android.browser.main.Constants @@ -58,8 +61,8 @@ class BrowserActivity : AppCompatActivity() { webView = findViewById(R.id.activity_main_web_view) webView!!.browserWebViewListener = browserWebViewListener progress = findViewById(R.id.activity_main_progress) - home = findViewById(R.id.activity_main_home) - home!!.setOnClickListener { loadHomePage() } + home = findViewById(R.id.activity_main_more) + home!!.setOnClickListener { showOverflowPopupMenu(home!!) } input = findViewById(R.id.activity_main_search) input!!.setOnEditorActionListener(createOnEditorActionListener()) @@ -107,6 +110,7 @@ class BrowserActivity : AppCompatActivity() { } private fun loadHomePage() { + setProgressBarProgress(0) webView!!.load(Constants.HOME_PAGE) } @@ -123,19 +127,25 @@ class BrowserActivity : AppCompatActivity() { return } progress!!.visibility = VISIBLE - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - progress!!.setProgress(progressPercent, true) - } else { - progress!!.progress = progressPercent - } + setProgressBarProgress(progressPercent) } } } + private fun setProgressBarProgress(progressPercent: Int) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + progress!!.setProgress(progressPercent, true) + } else { + progress!!.progress = progressPercent + } + } + private fun createOnEditorActionListener(): TextView.OnEditorActionListener { return TextView.OnEditorActionListener { v, _, _ -> - webView!!.load("https://www.google.fr/search?q=" + v!!.text.toString().replace(" ", "+")) + webView!!.load("https://www.google.fr/search?q=" + v!!.text.toString() + .replace(" ", "+")) appBarLayout!!.setExpanded(false) + input!!.setText("") KeyboardUtils.hideSoftInput(input!!) true } @@ -153,6 +163,30 @@ class BrowserActivity : AppCompatActivity() { } } + /** + * Show a popup menu which allows the user to perform action related to the video and the queue. + * + * @param view : The [View] on which the popup menu should be anchored. + */ + private fun showOverflowPopupMenu(view: View) { + val popupMenu = PopupMenu(this, view, Gravity.END) + popupMenu.menuInflater.inflate(R.menu.menu_browser, popupMenu.menu) + popupMenu.setOnMenuItemClickListener(createOnMenuItemClickListener()) + popupMenu.show() + } + + private fun createOnMenuItemClickListener(): PopupMenu.OnMenuItemClickListener? { + return PopupMenu.OnMenuItemClickListener { item -> + when (item!!.itemId) { + R.id.menu_browser_home -> loadHomePage() + R.id.menu_browser_clear_data -> webView!!.clearData() + R.id.menu_browser_settings -> Toast.makeText(this@BrowserActivity, + "Not yet", Toast.LENGTH_SHORT).show() + } + false + } + } + private fun updateTheme() { updateTheme(themeManager.theme) } diff --git a/app/src/main/java/com/mercandalli/android/browser/browser/BrowserUtils.java b/app/src/main/java/com/mercandalli/android/browser/browser/BrowserUtils.java deleted file mode 100644 index 9f9870d..0000000 --- a/app/src/main/java/com/mercandalli/android/browser/browser/BrowserUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.mercandalli.android.browser.browser; - -import android.content.Context; -import android.support.annotation.NonNull; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -/* package */ class BrowserUtils { - - private static String playerHtml; - - @NonNull - /* package */ static String getHtml(@NonNull final Context context) { - if (playerHtml == null) { - playerHtml = readFileAssets(context); - } - return playerHtml; - } - - @NonNull - private static String readFileAssets(@NonNull final Context context) { - try { - final StringBuilder buf = new StringBuilder(); - final InputStream json = context.getAssets().open("browser.html"); - final BufferedReader in = new BufferedReader(new InputStreamReader(json, "UTF-8")); - String str; - while ((str = in.readLine()) != null) { - buf.append(str).append('\n'); - } - in.close(); - return buf.toString(); - } catch (IOException ignored) { - } - return ""; - } -} diff --git a/app/src/main/java/com/mercandalli/android/browser/browser/BrowserWebView.kt b/app/src/main/java/com/mercandalli/android/browser/browser/BrowserWebView.kt index 7cc85d0..968d254 100644 --- a/app/src/main/java/com/mercandalli/android/browser/browser/BrowserWebView.kt +++ b/app/src/main/java/com/mercandalli/android/browser/browser/BrowserWebView.kt @@ -6,7 +6,6 @@ import android.util.AttributeSet import android.util.Log import android.view.View import android.webkit.* -import com.mercandalli.android.browser.main.Constants class BrowserWebView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 @@ -35,7 +34,7 @@ class BrowserWebView @JvmOverloads constructor( settings.setSupportZoom(true) settings.builtInZoomControls = true settings.displayZoomControls = false - settings.userAgentString = Constants.USER_AGENT + //settings.userAgentString = Constants.USER_AGENT webChromeClient = object : WebChromeClient() { override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean { @@ -67,18 +66,12 @@ class BrowserWebView @JvmOverloads constructor( } } + fun clearData() { + clearHistory() + clearCache(true) + } + fun load(url: String) { - /* - if(url.contains("youtube")) { - loadDataWithBaseURL( - "http://www.google.com/", - BrowserUtils.getHtml(context), - WEB_VIEW_MIME_TYPE, - WEB_VIEW_ENCODING, - "") - loadUrl(String.format("javascript:loadUrl(%s);", url)) - } - */ loadUrl(url) } diff --git a/app/src/main/java/com/mercandalli/android/browser/browser/NestedScrollWebView.java b/app/src/main/java/com/mercandalli/android/browser/browser/NestedScrollWebView.java deleted file mode 100644 index e63f5d9..0000000 --- a/app/src/main/java/com/mercandalli/android/browser/browser/NestedScrollWebView.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.mercandalli.android.browser.browser; - - -import android.content.Context; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.NestedScrollingChild; -import android.support.v4.view.NestedScrollingChildHelper; -import android.support.v4.view.ViewCompat; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.webkit.WebView; - -public class NestedScrollWebView extends WebView implements NestedScrollingChild { - - public static final String TAG = NestedScrollWebView.class.getSimpleName(); - - private int mLastMotionY; - - private final int[] mScrollOffset = new int[2]; - private final int[] mScrollConsumed = new int[2]; - - private int mNestedYOffset; - - private NestedScrollingChildHelper mChildHelper; - - public NestedScrollWebView(Context context) { - super(context); - init(); - } - - public NestedScrollWebView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public NestedScrollWebView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - mChildHelper = new NestedScrollingChildHelper(this); - setNestedScrollingEnabled(true); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - boolean result = false; - - MotionEvent trackedEvent = MotionEvent.obtain(event); - - final int action = MotionEventCompat.getActionMasked(event); - - if (action == MotionEvent.ACTION_DOWN) { - mNestedYOffset = 0; - } - - int y = (int) event.getY(); - - event.offsetLocation(0, mNestedYOffset); - - switch (action) { - case MotionEvent.ACTION_DOWN: - mLastMotionY = y; - startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL); - result = super.onTouchEvent(event); - break; - case MotionEvent.ACTION_MOVE: - int deltaY = mLastMotionY - y; - - if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) { - deltaY -= mScrollConsumed[1]; - trackedEvent.offsetLocation(0, mScrollOffset[1]); - mNestedYOffset += mScrollOffset[1]; - } - - mLastMotionY = y - mScrollOffset[1]; - - int oldY = getScrollY(); - int newScrollY = Math.max(0, oldY + deltaY); - int dyConsumed = newScrollY - oldY; - int dyUnconsumed = deltaY - dyConsumed; - - if (dispatchNestedScroll(0, dyConsumed, 0, dyUnconsumed, mScrollOffset)) { - mLastMotionY -= mScrollOffset[1]; - trackedEvent.offsetLocation(0, mScrollOffset[1]); - mNestedYOffset += mScrollOffset[1]; - } - - result = super.onTouchEvent(trackedEvent); - trackedEvent.recycle(); - break; - case MotionEvent.ACTION_POINTER_DOWN: - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - stopNestedScroll(); - result = super.onTouchEvent(event); - break; - } - return result; - } - - // NestedScrollingChild - - @Override - public void setNestedScrollingEnabled(boolean enabled) { - mChildHelper.setNestedScrollingEnabled(enabled); - } - - @Override - public boolean isNestedScrollingEnabled() { - return mChildHelper.isNestedScrollingEnabled(); - } - - @Override - public boolean startNestedScroll(int axes) { - return mChildHelper.startNestedScroll(axes); - } - - @Override - public void stopNestedScroll() { - mChildHelper.stopNestedScroll(); - } - - @Override - public boolean hasNestedScrollingParent() { - return mChildHelper.hasNestedScrollingParent(); - } - - @Override - public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { - return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); - } - - @Override - public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { - return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); - } - - @Override - public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { - return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); - } - - @Override - public boolean dispatchNestedPreFling(float velocityX, float velocityY) { - return mChildHelper.dispatchNestedPreFling(velocityX, velocityY); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/mercandalli/android/browser/browser/NestedScrollWebView.kt b/app/src/main/java/com/mercandalli/android/browser/browser/NestedScrollWebView.kt new file mode 100644 index 0000000..59dd356 --- /dev/null +++ b/app/src/main/java/com/mercandalli/android/browser/browser/NestedScrollWebView.kt @@ -0,0 +1,131 @@ +package com.mercandalli.android.browser.browser + +import android.content.Context +import android.support.v4.view.MotionEventCompat +import android.support.v4.view.NestedScrollingChild +import android.support.v4.view.NestedScrollingChildHelper +import android.support.v4.view.ViewCompat +import android.util.AttributeSet +import android.view.MotionEvent +import android.webkit.WebView + +open class NestedScrollWebView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : WebView(context, attrs, defStyleAttr), NestedScrollingChild { + + private var lastMotionY: Int = 0 + + private val scrollOffset = IntArray(2) + private val scrollConsumed = IntArray(2) + + private var nestedYOffset: Int = 0 + + private var childHelper: NestedScrollingChildHelper? = null + + init { + if (!isInEditMode) { + childHelper = NestedScrollingChildHelper(this) + isNestedScrollingEnabled = true + } + } + + override fun onTouchEvent(event: MotionEvent): Boolean { + var result = false + + val trackedEvent = MotionEvent.obtain(event) + + val action = MotionEventCompat.getActionMasked(event) + + if (action == MotionEvent.ACTION_DOWN) { + nestedYOffset = 0 + } + + val y = event.y.toInt() + + event.offsetLocation(0f, nestedYOffset.toFloat()) + + when (action) { + MotionEvent.ACTION_DOWN -> { + lastMotionY = y + startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL) + result = super.onTouchEvent(event) + } + MotionEvent.ACTION_MOVE -> { + var deltaY = lastMotionY - y + + if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) { + deltaY -= scrollConsumed[1] + trackedEvent.offsetLocation(0f, scrollOffset[1].toFloat()) + nestedYOffset += scrollOffset[1] + } + + lastMotionY = y - scrollOffset[1] + + val oldY = scrollY + val newScrollY = Math.max(0, oldY + deltaY) + val dyConsumed = newScrollY - oldY + val dyUnconsumed = deltaY - dyConsumed + + if (dispatchNestedScroll(0, dyConsumed, 0, dyUnconsumed, scrollOffset)) { + lastMotionY -= scrollOffset[1] + trackedEvent.offsetLocation(0f, scrollOffset[1].toFloat()) + nestedYOffset += scrollOffset[1] + } + + result = super.onTouchEvent(trackedEvent) + trackedEvent.recycle() + } + MotionEvent.ACTION_POINTER_DOWN, MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + stopNestedScroll() + result = super.onTouchEvent(event) + } + } + return result + } + + // NestedScrollingChild + + override fun setNestedScrollingEnabled(enabled: Boolean) { + childHelper!!.isNestedScrollingEnabled = enabled + } + + override fun isNestedScrollingEnabled(): Boolean { + return childHelper!!.isNestedScrollingEnabled + } + + override fun startNestedScroll(axes: Int): Boolean { + return childHelper!!.startNestedScroll(axes) + } + + override fun stopNestedScroll() { + childHelper!!.stopNestedScroll() + } + + override fun hasNestedScrollingParent(): Boolean { + return childHelper!!.hasNestedScrollingParent() + } + + override fun dispatchNestedScroll( + dxConsumed: Int, + dyConsumed: Int, + dxUnconsumed: Int, + dyUnconsumed: Int, + offsetInWindow: IntArray?): Boolean { + return childHelper!!.dispatchNestedScroll( + dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow) + } + + override fun dispatchNestedPreScroll( + dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?): Boolean { + return childHelper!!.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow) + } + + override fun dispatchNestedFling( + velocityX: Float, velocityY: Float, consumed: Boolean): Boolean { + return childHelper!!.dispatchNestedFling(velocityX, velocityY, consumed) + } + + override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean { + return childHelper!!.dispatchNestedPreFling(velocityX, velocityY) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mercandalli/android/browser/common/ForegroundImageView.kt b/app/src/main/java/com/mercandalli/android/browser/common/ForegroundImageView.kt new file mode 100644 index 0000000..f17ec76 --- /dev/null +++ b/app/src/main/java/com/mercandalli/android/browser/common/ForegroundImageView.kt @@ -0,0 +1,113 @@ +package com.mercandalli.android.browser.common + +import android.content.Context +import android.graphics.Canvas +import android.graphics.drawable.Drawable +import android.os.Build +import android.support.v4.content.ContextCompat +import android.support.v7.widget.AppCompatImageView +import android.util.AttributeSet +import com.mercandalli.android.browser.R + +/** + * An ImageView which supports a foreground drawable. + * + * + * https://gist.github.com/JakeWharton/0a251d67649305d84e8a + */ +class ForegroundImageView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null) : AppCompatImageView(context, attrs) { + + private var innerForeground: Drawable? = null + + init { + val typedArray = context.obtainStyledAttributes(attrs, + R.styleable.ForegroundImageView) + val foreground = typedArray + .getDrawable(R.styleable.ForegroundImageView_android_foreground) + if (foreground != null) { + setForeground(foreground) + } + typedArray.recycle() + } + + override fun jumpDrawablesToCurrentState() { + super.jumpDrawablesToCurrentState() + if (innerForeground != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + innerForeground!!.jumpToCurrentState() + } + } + + override fun verifyDrawable(who: Drawable): Boolean { + return super.verifyDrawable(who) || who === innerForeground + } + + override fun drawableStateChanged() { + super.drawableStateChanged() + if (innerForeground != null && innerForeground!!.isStateful) { + innerForeground!!.state = drawableState + } + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + if (innerForeground != null) { + innerForeground!!.setBounds(0, 0, measuredWidth, measuredHeight) + invalidate() + } + } + + override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) { + super.onSizeChanged(width, height, oldWidth, oldHeight) + if (innerForeground != null) { + innerForeground!!.setBounds(0, 0, width, height) + invalidate() + } + } + + override fun draw(canvas: Canvas) { + super.draw(canvas) + + if (innerForeground != null) { + innerForeground!!.draw(canvas) + } + } + + /** + * Supply a drawable resource that is to be rendered on top of all of the child + * views in the frame layout. + * + * @param drawableResId The drawable resource to be drawn on top of the children. + */ + fun setForegroundResource(drawableResId: Int) { + setForeground(ContextCompat.getDrawable(context, drawableResId)) + } + + /** + * Supply a Drawable that is to be rendered on top of all of the child + * views in the frame layout. + * + * @param drawable The Drawable to be drawn on top of the children. + */ + override fun setForeground(drawable: Drawable?) { + if (innerForeground === drawable) { + return + } + if (innerForeground != null) { + innerForeground!!.callback = null + unscheduleDrawable(innerForeground) + } + + innerForeground = drawable + + if (drawable != null) { + drawable.callback = this + if (drawable.isStateful) { + drawable.state = drawableState + } + } + requestLayout() + invalidate() + } +} + diff --git a/app/src/main/res/browser/drawable/ic_more_vert_black_24dp.xml b/app/src/main/res/browser/drawable/ic_more_vert_black_24dp.xml new file mode 100644 index 0000000..5176d8a --- /dev/null +++ b/app/src/main/res/browser/drawable/ic_more_vert_black_24dp.xml @@ -0,0 +1,9 @@ +