diff options
author | RaindropsSys <raindrops@equestria.dev> | 2023-12-17 12:24:41 +0100 |
---|---|---|
committer | RaindropsSys <raindrops@equestria.dev> | 2023-12-17 12:24:41 +0100 |
commit | 9d6d58c902a6e1551336e124eac6c2747610dc19 (patch) | |
tree | 2502a67310229295f6a850e3b7f82bafce7f1e35 | |
parent | 526d307826dfe3dc7f9e624913feaab3bee43b75 (diff) | |
download | ponywatch-9d6d58c902a6e1551336e124eac6c2747610dc19.tar.gz ponywatch-9d6d58c902a6e1551336e124eac6c2747610dc19.tar.bz2 ponywatch-9d6d58c902a6e1551336e124eac6c2747610dc19.zip |
Updated 13 files and added 7 files (automated)
20 files changed, 1259 insertions, 26 deletions
diff --git a/app/build.gradle b/app/build.gradle index 2b7c6bf..bac5400 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "dev.equestria.ponywatch" minSdk 30 targetSdk 33 - versionCode 8 - versionName "4.0" + versionCode 9 + versionName "5.0" } diff --git a/app/general/release/app-general-release.apk b/app/general/release/app-general-release.apk Binary files differindex 58e5872..182b89e 100644 --- a/app/general/release/app-general-release.apk +++ b/app/general/release/app-general-release.apk diff --git a/app/general/release/output-metadata.json b/app/general/release/output-metadata.json index e360245..915076d 100644 --- a/app/general/release/output-metadata.json +++ b/app/general/release/output-metadata.json @@ -11,8 +11,8 @@ "type": "SINGLE", "filters": [], "attributes": [], - "versionCode": 4, - "versionName": "2.1.general", + "versionCode": 9, + "versionName": "5.0.general", "outputFile": "app-general-release.apk" } ], diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 29e8a55..f9818b8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -176,6 +176,58 @@ </intent-filter> </service> + <service + android:name=".BlueyBlueyFace" + android:exported="true" + android:label="Bluey" + android:permission="android.permission.BIND_WALLPAPER"> + + <meta-data + android:name="android.service.wallpaper.square_mode" + android:value="false" /> + <meta-data + android:name="android.service.wallpaper" + android:resource="@xml/watch_face" /> + <meta-data + android:name="com.google.android.wearable.watchface.preview" + android:resource="@drawable/preview_bluey_bluey" /> + <meta-data + android:name="com.google.android.wearable.watchface.preview_circular" + android:resource="@drawable/preview_bluey_bluey" /> + + <intent-filter> + <action android:name="android.service.wallpaper.WallpaperService" /> + + <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" /> + </intent-filter> + </service> + + <service + android:name=".BlueyBingoFace" + android:exported="true" + android:label="Bingo" + android:permission="android.permission.BIND_WALLPAPER"> + + <meta-data + android:name="android.service.wallpaper.square_mode" + android:value="false" /> + <meta-data + android:name="android.service.wallpaper" + android:resource="@xml/watch_face" /> + <meta-data + android:name="com.google.android.wearable.watchface.preview" + android:resource="@drawable/preview_bluey_bingo" /> + <meta-data + android:name="com.google.android.wearable.watchface.preview_circular" + android:resource="@drawable/preview_bluey_bingo" /> + + <intent-filter> + <action android:name="android.service.wallpaper.WallpaperService" /> + + <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" /> + </intent-filter> + </service> + <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> diff --git a/app/src/main/java/dev/equestria/ponywatch/AlicornFace.kt b/app/src/main/java/dev/equestria/ponywatch/AlicornFace.kt index 6a46dfd..5b09e4e 100644 --- a/app/src/main/java/dev/equestria/ponywatch/AlicornFace.kt +++ b/app/src/main/java/dev/equestria/ponywatch/AlicornFace.kt @@ -369,7 +369,7 @@ class AlicornFace : CanvasWatchFaceService() { val volleyQueue = Volley.newRequestQueue(baseContext) - val jsonObjectRequest = JsonObjectRequest("https://ponies.equestria.horse/api/raindrops-two", + val jsonObjectRequest = JsonObjectRequest("https://ponycule.equestria.horse/api/raindrops-two", { response -> Log.i("HTTPRequest", response.toString()) @@ -400,7 +400,7 @@ class AlicornFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img2-round" + "https://ponycule.equestria.horse/api/raindrops-img2-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } }, @@ -418,7 +418,7 @@ class AlicornFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img-round" + "https://ponycule.equestria.horse/api/raindrops-img-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } else { if (twoFronters) { diff --git a/app/src/main/java/dev/equestria/ponywatch/BlueyBingoFace.kt b/app/src/main/java/dev/equestria/ponywatch/BlueyBingoFace.kt new file mode 100644 index 0000000..66c0cbb --- /dev/null +++ b/app/src/main/java/dev/equestria/ponywatch/BlueyBingoFace.kt @@ -0,0 +1,588 @@ +package dev.equestria.ponywatch + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.ColorMatrix +import android.graphics.ColorMatrixColorFilter +import android.graphics.Paint +import android.graphics.Rect +import android.graphics.RectF +import android.graphics.drawable.Drawable +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.support.wearable.watchface.CanvasWatchFaceService +import android.support.wearable.watchface.WatchFaceStyle +import android.util.Log +import android.view.SurfaceHolder +import android.widget.Toast +import com.android.volley.toolbox.JsonObjectRequest +import com.android.volley.toolbox.Volley +import com.squareup.picasso.MemoryPolicy +import com.squareup.picasso.Picasso +import com.squareup.picasso.Target +import java.lang.ref.WeakReference +import java.util.Calendar +import java.util.TimeZone + + +/** + * Updates rate in milliseconds for interactive mode. We update once a second to advance the + * second hand. + */ +private const val INTERACTIVE_UPDATE_RATE_MS = 16 + +/** + * Handler message id for updating the time periodically in interactive mode. + */ +private const val MSG_UPDATE_TIME = 0 + +private const val HOUR_STROKE_WIDTH = 35f +private const val MINUTE_STROKE_WIDTH = 7f +private const val SECOND_TICK_STROKE_WIDTH = 3f + +private const val CENTER_GAP_AND_CIRCLE_RADIUS = 4f + +private const val SHADOW_RADIUS = 3f + +/** + * Analog watch face with a ticking second hand. In ambient mode, the second hand isn"t + * shown. On devices with low-bit ambient mode, the hands are drawn without anti-aliasing in ambient + * mode. The watch face is drawn with less contrast in mute mode. + * + * + * Important Note: Because watch face apps do not have a default Activity in + * their project, you will need to set your Configurations to + * "Do not launch Activity" for both the Wear and/or Application modules. If you + * are unsure how to do this, please review the "Run Starter project" section + * in the Google Watch Face Code Lab: + * https://codelabs.developers.google.com/codelabs/watchface/index.html#0 + */ +class BlueyBingoFace : CanvasWatchFaceService() { + + override fun onCreateEngine(): Engine { + return Engine() + } + + private class EngineHandler(reference: BlueyBingoFace.Engine) : Handler(Looper.myLooper()!!) { + private val mWeakReference: WeakReference<Engine> = WeakReference(reference) + + override fun handleMessage(msg: Message) { + val engine = mWeakReference.get() + if (engine != null) { + when (msg.what) { + MSG_UPDATE_TIME -> engine.handleUpdateTimeMessage() + } + } + } + } + + inner class Engine : CanvasWatchFaceService.Engine() { + + private lateinit var mCalendar: Calendar + + private var mRegisteredTimeZoneReceiver = false + private var mMuteMode: Boolean = false + private var showDate: Boolean = false + private var mCenterX: Float = 0F + private var mCenterY: Float = 0F + private var mHeight: Float = 0F + + private var lastRefreshMinute: Int = -1 + + private var mSecondHandLength: Float = 0F + private var sMinuteHandLength: Float = 0F + private var sHourHandLength: Float = 0F + + /* Colors for all hands (hour, minute, seconds, ticks) based on photo loaded. */ + private var mWatchHandColor: Int = 0 + private var mWatchHandHighlightColor: Int = 0 + private var mWatchHandShadowColor: Int = 0 + + private lateinit var mBackgroundPaint: Paint + private lateinit var mBackgroundBitmap: Bitmap + private lateinit var mGrayBackgroundBitmap: Bitmap + + private var mAmbient: Boolean = false + private var mLowBitAmbient: Boolean = false + private var mBurnInProtection: Boolean = false + + private var currentDay: Int = 0 + private var currentHour: Int = 0 + private var twoFronters: Boolean = false + private var bmp: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.default_pony) + private var bmp2: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.default_pony) + + /* Handler to update the time once a second in interactive mode. */ + private val mUpdateTimeHandler = EngineHandler(this) + + private val mTimeZoneReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + mCalendar.timeZone = TimeZone.getDefault() + invalidate() + } + } + + override fun onCreate(holder: SurfaceHolder) { + super.onCreate(holder) + + setWatchFaceStyle( + WatchFaceStyle.Builder(this@BlueyBingoFace) + .setAcceptsTapEvents(true) + .build() + ) + + mCalendar = Calendar.getInstance() + + initializeBackground() + initializeWatchFace() + } + + private fun initializeBackground() { + mBackgroundPaint = Paint().apply { + color = Color.BLACK + } + mBackgroundBitmap = + BitmapFactory.decodeResource( + resources, R.drawable.watchface_bluey_bingo + ) + } + + private fun initializeWatchFace() { + /* Set defaults for colors */ + mWatchHandShadowColor = R.color.cutiemark_shadow + } + + override fun onDestroy() { + mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME) + super.onDestroy() + } + + override fun onPropertiesChanged(properties: Bundle) { + super.onPropertiesChanged(properties) + mLowBitAmbient = properties.getBoolean( + PROPERTY_LOW_BIT_AMBIENT, false + ) + mBurnInProtection = properties.getBoolean( + PROPERTY_BURN_IN_PROTECTION, false + ) + } + + override fun onTimeTick() { + super.onTimeTick() + invalidate() + } + + override fun onAmbientModeChanged(inAmbientMode: Boolean) { + super.onAmbientModeChanged(inAmbientMode) + mAmbient = inAmbientMode + + // Check and trigger whether or not timer should be running (only + // in active mode). + updateTimer() + } + + override fun onInterruptionFilterChanged(interruptionFilter: Int) { + super.onInterruptionFilterChanged(interruptionFilter) + val inMuteMode = interruptionFilter == INTERRUPTION_FILTER_NONE + + /* Dim display in mute mode. */ + if (mMuteMode != inMuteMode) { + mMuteMode = inMuteMode + invalidate() + } + } + + override fun onSurfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + super.onSurfaceChanged(holder, format, width, height) + + /* + * Find the coordinates of the center point on the screen, and ignore the window + * insets, so that, on round watches with a "chin", the watch face is centered on the + * entire screen, not just the usable portion. + */ + mCenterX = width / 2f + mCenterY = height / 2f + mHeight = height.toFloat() + + /* + * Calculate lengths of different hands based on watch screen size. + */ + mSecondHandLength = (mCenterX * 0.875).toFloat() + sMinuteHandLength = (mCenterX * 0.75).toFloat() + sHourHandLength = (mCenterX * 0.5).toFloat() + + /* Scale loaded background image (more efficient) if surface dimensions change. */ + val scale = width.toFloat() / mBackgroundBitmap.width.toFloat() + + mBackgroundBitmap = Bitmap.createScaledBitmap( + mBackgroundBitmap, + (mBackgroundBitmap.width * scale).toInt(), + (mBackgroundBitmap.height * scale).toInt(), true + ) + + /* + * Create a gray version of the image only if it will look nice on the device in + * ambient mode. That means we don"t want devices that support burn-in + * protection (slight movements in pixels, not great for images going all the way to + * edges) and low ambient mode (degrades image quality). + * + * Also, if your watch face will know about all images ahead of time (users aren"t + * selecting their own photos for the watch face), it will be more + * efficient to create a black/white version (png, etc.) and load that when you need it. + */ + if (!mBurnInProtection && !mLowBitAmbient) { + initGrayBackgroundBitmap() + } + } + + private fun initGrayBackgroundBitmap() { + mGrayBackgroundBitmap = Bitmap.createBitmap( + mBackgroundBitmap.width, + mBackgroundBitmap.height, + Bitmap.Config.ARGB_8888 + ) + val canvas = Canvas(mGrayBackgroundBitmap) + val grayPaint = Paint() + val colorMatrix = ColorMatrix() + colorMatrix.setSaturation(0f) + val filter = ColorMatrixColorFilter(colorMatrix) + grayPaint.colorFilter = filter + canvas.drawBitmap(mBackgroundBitmap, 0f, 0f, grayPaint) + } + + /** + * Captures tap event (and tap type). The [WatchFaceService.TAP_TYPE_TAP] case can be + * used for implementing specific logic to handle the gesture. + */ + override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) { + when (tapType) { + TAP_TYPE_TOUCH -> { + // The user has started touching the screen. + if (x < mCenterX / 4) showDate = true + } + TAP_TYPE_TOUCH_CANCEL -> { + // The user has started a different gesture or otherwise cancelled the tap. + showDate = false + } + TAP_TYPE_TAP -> { + // The user has completed the tap gesture. + // TODO: Add code to handle the tap gesture. + /*Toast.makeText(applicationContext, "tap", Toast.LENGTH_SHORT) + .show()*/ + showDate = false + } + } + invalidate() + } + + override fun onDraw(canvas: Canvas, bounds: Rect) { + val now = System.currentTimeMillis() + mCalendar.timeInMillis = now + + drawBackground(canvas) + drawWatchFace(canvas) + } + + private fun drawBackground(canvas: Canvas) { + + if (mAmbient && (mLowBitAmbient || mBurnInProtection)) { + canvas.drawColor(Color.BLACK) + } else if (mAmbient) { + canvas.drawBitmap(mGrayBackgroundBitmap, 0f, 0f, mBackgroundPaint) + } else { + canvas.drawBitmap(mBackgroundBitmap, 0f, 0f, mBackgroundPaint) + } + } + + private fun drawWatchFace(canvas: Canvas) { + + /* + * Draw ticks. Usually you will want to bake this directly into the photo, but in + * cases where you want to allow users to select their own photos, this dynamically + * creates them on top of the photo. + */ + /*val innerTickRadius = mCenterX - 10 + val outerTickRadius = mCenterX + for (tickIndex in 0..11) { + val tickRot = (tickIndex.toDouble() * Math.PI * 2.0 / 12).toFloat() + val innerX = Math.sin(tickRot.toDouble()).toFloat() * innerTickRadius + val innerY = (-Math.cos(tickRot.toDouble())).toFloat() * innerTickRadius + val outerX = Math.sin(tickRot.toDouble()).toFloat() * outerTickRadius + val outerY = (-Math.cos(tickRot.toDouble())).toFloat() * outerTickRadius + canvas.drawLine( + mCenterX + innerX, mCenterY + innerY, + mCenterX + outerX, mCenterY + outerY, mTickAndCirclePaint + ) + }*/ + + /* + * Save the canvas state before we can begin to rotate it. + */ + canvas.save() + + /* Restore the canvas" original orientation. */ + canvas.restore() + + val paint = Paint().apply { + color = resources.getColor(R.color.bluey_bingo_text) + isAntiAlias = true + setShadowLayer( + 1.5f, 0f, 0f, mWatchHandShadowColor + ) + } + + paint.textAlign = Paint.Align.CENTER + paint.textSize = 96f + paint.typeface = resources.getFont(R.font.bluey_font) + + val h = mCalendar.get(Calendar.HOUR_OF_DAY) + val hs = if (h < 10) { + "0$h" + } else { + h.toString() + } + + val m = mCalendar.get(Calendar.MINUTE) + val ms = if (m < 10) { + "0$m" + } else { + m.toString() + } + + val d = mCalendar.get(Calendar.DAY_OF_MONTH) + val i = mCalendar.get(Calendar.MONTH) + + canvas.drawText("$hs:$ms", (canvas.width / 2).toFloat(), 116f, paint) + + if (showDate) { + val it = when (i) { + 0 -> "jan" + 1 -> "feb" + 2 -> "mar" + 3 -> "apr" + 4 -> "may" + 5 -> "jun" + 6 -> "jul" + 7 -> "aug" + 8 -> "sep" + 9 -> "oct" + 10 -> "nov" + 11 -> "dec" + else -> i + } + + paint.textSize = 36f + paint.alpha = 191 + + canvas.drawText("$d", canvas.width - 48f, (canvas.height / 2).toFloat() - 20f + 7f, paint) + canvas.drawText("$it", canvas.width - 48f, (canvas.height / 2).toFloat() + 20f + 7f, paint) + } + + if (BuildConfig.ENABLE_PLURALITY) { + if (mCalendar.get(Calendar.MINUTE) != lastRefreshMinute) { + lastRefreshMinute = mCalendar.get(Calendar.MINUTE) + + val target = object : Target { + override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) { + try { + if (bitmap != null) { + bmp = bitmap + bmp = Bitmap.createScaledBitmap( + bmp, + 36, + 36, true + ) + bmp.prepareToDraw() + + if (showDate) { + canvas.drawBitmap(bmp, mCenterX - 36f/2f, 0f, mBackgroundPaint) + } + } + } catch (ex: IllegalArgumentException) { + Log.e("Picasso", ex.toString()) + } + + val volleyQueue = Volley.newRequestQueue(baseContext) + + val jsonObjectRequest = + JsonObjectRequest("https://ponycule.equestria.horse/api/raindrops-two", + + { response -> + Log.i("HTTPRequest", response.toString()) + twoFronters = response!!.get("multiple") as Boolean + + if (twoFronters) { + val target = object : Target { + override fun onBitmapLoaded( + bitmap: Bitmap?, + from: Picasso.LoadedFrom? + ) { + try { + if (bitmap != null) { + bmp2 = bitmap + bmp2 = Bitmap.createScaledBitmap( + bmp2, + 36, + 36, true + ) + bmp2.prepareToDraw() + } + } catch (ex: IllegalArgumentException) { + Log.e("Picasso", ex.toString()) + } + } + + override fun onBitmapFailed( + e: Exception?, + errorDrawable: Drawable? + ) { + Log.e("Picasso", e.toString()) + } + + override fun onPrepareLoad(placeHolderDrawable: Drawable?) {} + } + + Picasso.get().load( + "https://ponycule.equestria.horse/api/raindrops-img2-round2" + ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) + } + }, + + { error -> + Log.e( + "HTTPRequest", + "Request error: ${error.localizedMessage}" + ) + }) + + volleyQueue.add(jsonObjectRequest) + } + + override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) { + Log.e("Picasso", e.toString()) + } + + override fun onPrepareLoad(placeHolderDrawable: Drawable?) {} + } + + Picasso.get().load( + "https://ponycule.equestria.horse/api/raindrops-img-round2" + ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) + } else { + if (showDate) { + if (twoFronters) { + canvas.drawBitmap(bmp2, mCenterX - 4f/2f, 0f, mBackgroundPaint) + canvas.drawBitmap(bmp, mCenterX - 88f/2f, 0f, mBackgroundPaint) + } else { + canvas.drawBitmap(bmp, mCenterX - 36f/2f, 0f, mBackgroundPaint) + } + } + } + } + + val paintOut2 = Paint().apply { + color = resources.getColor(R.color.bluey_bingo_circle) + style = Paint.Style.STROKE + strokeWidth = 15f + strokeCap = Paint.Cap.ROUND + isAntiAlias = true + setShadowLayer( + 1.5f, 0f, 0f, resources.getColor(R.color.cutiemark_shadow) + ) + } + + val seconds = + mCalendar.get(Calendar.SECOND) + mCalendar.get(Calendar.MILLISECOND) / 1000f + val secondsRotation = seconds * 6f + + val currentDayFetched = mCalendar.get(Calendar.DAY_OF_WEEK) - 1 + val currentHourFetched = mCalendar.get(Calendar.HOUR_OF_DAY) + + if (currentDayFetched > currentDay || currentDayFetched < currentDay) { + currentDay = currentDayFetched + initializeBackground() + initializeWatchFace() + } + + if (currentHourFetched > currentHour || currentHourFetched < currentHour) { + currentHour = currentHourFetched + initializeBackground() + initializeWatchFace() + } + + canvas.drawArc(10f, 10f, mCenterX * 2f - 10f, mCenterY * 2f - 10f, secondsRotation - 1f + 270f, 0.15f, false, paintOut2) + } + + override fun onVisibilityChanged(visible: Boolean) { + super.onVisibilityChanged(visible) + + if (visible) { + registerReceiver() + /* Update time zone in case it changed while we weren"t visible. */ + mCalendar.timeZone = TimeZone.getDefault() + invalidate() + } else { + showDate = false + unregisterReceiver() + } + + /* Check and trigger whether or not timer should be running (only in active mode). */ + updateTimer() + } + + private fun registerReceiver() { + if (mRegisteredTimeZoneReceiver) { + return + } + mRegisteredTimeZoneReceiver = true + val filter = IntentFilter(Intent.ACTION_TIMEZONE_CHANGED) + this@BlueyBingoFace.registerReceiver(mTimeZoneReceiver, filter) + } + + private fun unregisterReceiver() { + if (!mRegisteredTimeZoneReceiver) { + return + } + mRegisteredTimeZoneReceiver = false + this@BlueyBingoFace.unregisterReceiver(mTimeZoneReceiver) + } + + /** + * Starts/stops the [.mUpdateTimeHandler] timer based on the state of the watch face. + */ + private fun updateTimer() { + mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME) + if (shouldTimerBeRunning()) { + mUpdateTimeHandler.sendEmptyMessage(MSG_UPDATE_TIME) + } + } + + /** + * Returns whether the [.mUpdateTimeHandler] timer should be running. The timer + * should only run in active mode. + */ + private fun shouldTimerBeRunning(): Boolean { + return isVisible && !mAmbient + } + + /** + * Handle updating the time periodically in interactive mode. + */ + fun handleUpdateTimeMessage() { + invalidate() + if (shouldTimerBeRunning()) { + val timeMs = System.currentTimeMillis() + val delayMs = INTERACTIVE_UPDATE_RATE_MS - timeMs % INTERACTIVE_UPDATE_RATE_MS + mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs) + } + } + } +}
\ No newline at end of file diff --git a/app/src/main/java/dev/equestria/ponywatch/BlueyBlueyFace.kt b/app/src/main/java/dev/equestria/ponywatch/BlueyBlueyFace.kt new file mode 100644 index 0000000..2dd109c --- /dev/null +++ b/app/src/main/java/dev/equestria/ponywatch/BlueyBlueyFace.kt @@ -0,0 +1,588 @@ +package dev.equestria.ponywatch + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.ColorMatrix +import android.graphics.ColorMatrixColorFilter +import android.graphics.Paint +import android.graphics.Rect +import android.graphics.RectF +import android.graphics.drawable.Drawable +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.support.wearable.watchface.CanvasWatchFaceService +import android.support.wearable.watchface.WatchFaceStyle +import android.util.Log +import android.view.SurfaceHolder +import android.widget.Toast +import com.android.volley.toolbox.JsonObjectRequest +import com.android.volley.toolbox.Volley +import com.squareup.picasso.MemoryPolicy +import com.squareup.picasso.Picasso +import com.squareup.picasso.Target +import java.lang.ref.WeakReference +import java.util.Calendar +import java.util.TimeZone + + +/** + * Updates rate in milliseconds for interactive mode. We update once a second to advance the + * second hand. + */ +private const val INTERACTIVE_UPDATE_RATE_MS = 16 + +/** + * Handler message id for updating the time periodically in interactive mode. + */ +private const val MSG_UPDATE_TIME = 0 + +private const val HOUR_STROKE_WIDTH = 35f +private const val MINUTE_STROKE_WIDTH = 7f +private const val SECOND_TICK_STROKE_WIDTH = 3f + +private const val CENTER_GAP_AND_CIRCLE_RADIUS = 4f + +private const val SHADOW_RADIUS = 3f + +/** + * Analog watch face with a ticking second hand. In ambient mode, the second hand isn"t + * shown. On devices with low-bit ambient mode, the hands are drawn without anti-aliasing in ambient + * mode. The watch face is drawn with less contrast in mute mode. + * + * + * Important Note: Because watch face apps do not have a default Activity in + * their project, you will need to set your Configurations to + * "Do not launch Activity" for both the Wear and/or Application modules. If you + * are unsure how to do this, please review the "Run Starter project" section + * in the Google Watch Face Code Lab: + * https://codelabs.developers.google.com/codelabs/watchface/index.html#0 + */ +class BlueyBlueyFace : CanvasWatchFaceService() { + + override fun onCreateEngine(): Engine { + return Engine() + } + + private class EngineHandler(reference: BlueyBlueyFace.Engine) : Handler(Looper.myLooper()!!) { + private val mWeakReference: WeakReference<Engine> = WeakReference(reference) + + override fun handleMessage(msg: Message) { + val engine = mWeakReference.get() + if (engine != null) { + when (msg.what) { + MSG_UPDATE_TIME -> engine.handleUpdateTimeMessage() + } + } + } + } + + inner class Engine : CanvasWatchFaceService.Engine() { + + private lateinit var mCalendar: Calendar + + private var mRegisteredTimeZoneReceiver = false + private var mMuteMode: Boolean = false + private var showDate: Boolean = false + private var mCenterX: Float = 0F + private var mCenterY: Float = 0F + private var mHeight: Float = 0F + + private var lastRefreshMinute: Int = -1 + + private var mSecondHandLength: Float = 0F + private var sMinuteHandLength: Float = 0F + private var sHourHandLength: Float = 0F + + /* Colors for all hands (hour, minute, seconds, ticks) based on photo loaded. */ + private var mWatchHandColor: Int = 0 + private var mWatchHandHighlightColor: Int = 0 + private var mWatchHandShadowColor: Int = 0 + + private lateinit var mBackgroundPaint: Paint + private lateinit var mBackgroundBitmap: Bitmap + private lateinit var mGrayBackgroundBitmap: Bitmap + + private var mAmbient: Boolean = false + private var mLowBitAmbient: Boolean = false + private var mBurnInProtection: Boolean = false + + private var currentDay: Int = 0 + private var currentHour: Int = 0 + private var twoFronters: Boolean = false + private var bmp: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.default_pony) + private var bmp2: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.default_pony) + + /* Handler to update the time once a second in interactive mode. */ + private val mUpdateTimeHandler = EngineHandler(this) + + private val mTimeZoneReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + mCalendar.timeZone = TimeZone.getDefault() + invalidate() + } + } + + override fun onCreate(holder: SurfaceHolder) { + super.onCreate(holder) + + setWatchFaceStyle( + WatchFaceStyle.Builder(this@BlueyBlueyFace) + .setAcceptsTapEvents(true) + .build() + ) + + mCalendar = Calendar.getInstance() + + initializeBackground() + initializeWatchFace() + } + + private fun initializeBackground() { + mBackgroundPaint = Paint().apply { + color = Color.BLACK + } + mBackgroundBitmap = + BitmapFactory.decodeResource( + resources, R.drawable.watchface_bluey_bluey + ) + } + + private fun initializeWatchFace() { + /* Set defaults for colors */ + mWatchHandShadowColor = R.color.cutiemark_shadow + } + + override fun onDestroy() { + mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME) + super.onDestroy() + } + + override fun onPropertiesChanged(properties: Bundle) { + super.onPropertiesChanged(properties) + mLowBitAmbient = properties.getBoolean( + PROPERTY_LOW_BIT_AMBIENT, false + ) + mBurnInProtection = properties.getBoolean( + PROPERTY_BURN_IN_PROTECTION, false + ) + } + + override fun onTimeTick() { + super.onTimeTick() + invalidate() + } + + override fun onAmbientModeChanged(inAmbientMode: Boolean) { + super.onAmbientModeChanged(inAmbientMode) + mAmbient = inAmbientMode + + // Check and trigger whether or not timer should be running (only + // in active mode). + updateTimer() + } + + override fun onInterruptionFilterChanged(interruptionFilter: Int) { + super.onInterruptionFilterChanged(interruptionFilter) + val inMuteMode = interruptionFilter == INTERRUPTION_FILTER_NONE + + /* Dim display in mute mode. */ + if (mMuteMode != inMuteMode) { + mMuteMode = inMuteMode + invalidate() + } + } + + override fun onSurfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + super.onSurfaceChanged(holder, format, width, height) + + /* + * Find the coordinates of the center point on the screen, and ignore the window + * insets, so that, on round watches with a "chin", the watch face is centered on the + * entire screen, not just the usable portion. + */ + mCenterX = width / 2f + mCenterY = height / 2f + mHeight = height.toFloat() + + /* + * Calculate lengths of different hands based on watch screen size. + */ + mSecondHandLength = (mCenterX * 0.875).toFloat() + sMinuteHandLength = (mCenterX * 0.75).toFloat() + sHourHandLength = (mCenterX * 0.5).toFloat() + + /* Scale loaded background image (more efficient) if surface dimensions change. */ + val scale = width.toFloat() / mBackgroundBitmap.width.toFloat() + + mBackgroundBitmap = Bitmap.createScaledBitmap( + mBackgroundBitmap, + (mBackgroundBitmap.width * scale).toInt(), + (mBackgroundBitmap.height * scale).toInt(), true + ) + + /* + * Create a gray version of the image only if it will look nice on the device in + * ambient mode. That means we don"t want devices that support burn-in + * protection (slight movements in pixels, not great for images going all the way to + * edges) and low ambient mode (degrades image quality). + * + * Also, if your watch face will know about all images ahead of time (users aren"t + * selecting their own photos for the watch face), it will be more + * efficient to create a black/white version (png, etc.) and load that when you need it. + */ + if (!mBurnInProtection && !mLowBitAmbient) { + initGrayBackgroundBitmap() + } + } + + private fun initGrayBackgroundBitmap() { + mGrayBackgroundBitmap = Bitmap.createBitmap( + mBackgroundBitmap.width, + mBackgroundBitmap.height, + Bitmap.Config.ARGB_8888 + ) + val canvas = Canvas(mGrayBackgroundBitmap) + val grayPaint = Paint() + val colorMatrix = ColorMatrix() + colorMatrix.setSaturation(0f) + val filter = ColorMatrixColorFilter(colorMatrix) + grayPaint.colorFilter = filter + canvas.drawBitmap(mBackgroundBitmap, 0f, 0f, grayPaint) + } + + /** + * Captures tap event (and tap type). The [WatchFaceService.TAP_TYPE_TAP] case can be + * used for implementing specific logic to handle the gesture. + */ + override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) { + when (tapType) { + TAP_TYPE_TOUCH -> { + // The user has started touching the screen. + if (x < mCenterX / 4) showDate = true + } + TAP_TYPE_TOUCH_CANCEL -> { + // The user has started a different gesture or otherwise cancelled the tap. + showDate = false + } + TAP_TYPE_TAP -> { + // The user has completed the tap gesture. + // TODO: Add code to handle the tap gesture. + /*Toast.makeText(applicationContext, "tap", Toast.LENGTH_SHORT) + .show()*/ + showDate = false + } + } + invalidate() + } + + override fun onDraw(canvas: Canvas, bounds: Rect) { + val now = System.currentTimeMillis() + mCalendar.timeInMillis = now + + drawBackground(canvas) + drawWatchFace(canvas) + } + + private fun drawBackground(canvas: Canvas) { + + if (mAmbient && (mLowBitAmbient || mBurnInProtection)) { + canvas.drawColor(Color.BLACK) + } else if (mAmbient) { + canvas.drawBitmap(mGrayBackgroundBitmap, 0f, 0f, mBackgroundPaint) + } else { + canvas.drawBitmap(mBackgroundBitmap, 0f, 0f, mBackgroundPaint) + } + } + + private fun drawWatchFace(canvas: Canvas) { + + /* + * Draw ticks. Usually you will want to bake this directly into the photo, but in + * cases where you want to allow users to select their own photos, this dynamically + * creates them on top of the photo. + */ + /*val innerTickRadius = mCenterX - 10 + val outerTickRadius = mCenterX + for (tickIndex in 0..11) { + val tickRot = (tickIndex.toDouble() * Math.PI * 2.0 / 12).toFloat() + val innerX = Math.sin(tickRot.toDouble()).toFloat() * innerTickRadius + val innerY = (-Math.cos(tickRot.toDouble())).toFloat() * innerTickRadius + val outerX = Math.sin(tickRot.toDouble()).toFloat() * outerTickRadius + val outerY = (-Math.cos(tickRot.toDouble())).toFloat() * outerTickRadius + canvas.drawLine( + mCenterX + innerX, mCenterY + innerY, + mCenterX + outerX, mCenterY + outerY, mTickAndCirclePaint + ) + }*/ + + /* + * Save the canvas state before we can begin to rotate it. + */ + canvas.save() + + /* Restore the canvas" original orientation. */ + canvas.restore() + + val paint = Paint().apply { + color = resources.getColor(R.color.bluey_bluey_text) + isAntiAlias = true + setShadowLayer( + 1.5f, 0f, 0f, mWatchHandShadowColor + ) + } + + paint.textAlign = Paint.Align.CENTER + paint.textSize = 96f + paint.typeface = resources.getFont(R.font.bluey_font) + + val h = mCalendar.get(Calendar.HOUR_OF_DAY) + val hs = if (h < 10) { + "0$h" + } else { + h.toString() + } + + val m = mCalendar.get(Calendar.MINUTE) + val ms = if (m < 10) { + "0$m" + } else { + m.toString() + } + + val d = mCalendar.get(Calendar.DAY_OF_MONTH) + val i = mCalendar.get(Calendar.MONTH) + + canvas.drawText("$hs:$ms", (canvas.width / 2).toFloat(), 116f, paint) + + if (showDate) { + val it = when (i) { + 0 -> "jan" + 1 -> "feb" + 2 -> "mar" + 3 -> "apr" + 4 -> "may" + 5 -> "jun" + 6 -> "jul" + 7 -> "aug" + 8 -> "sep" + 9 -> "oct" + 10 -> "nov" + 11 -> "dec" + else -> i + } + + paint.textSize = 36f + paint.alpha = 191 + + canvas.drawText("$d", canvas.width - 48f, (canvas.height / 2).toFloat() - 20f + 7f, paint) + canvas.drawText("$it", canvas.width - 48f, (canvas.height / 2).toFloat() + 20f + 7f, paint) + } + + if (BuildConfig.ENABLE_PLURALITY) { + if (mCalendar.get(Calendar.MINUTE) != lastRefreshMinute) { + lastRefreshMinute = mCalendar.get(Calendar.MINUTE) + + val target = object : Target { + override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) { + try { + if (bitmap != null) { + bmp = bitmap + bmp = Bitmap.createScaledBitmap( + bmp, + 36, + 36, true + ) + bmp.prepareToDraw() + + if (showDate) { + canvas.drawBitmap(bmp, mCenterX - 36f/2f, 0f, mBackgroundPaint) + } + } + } catch (ex: IllegalArgumentException) { + Log.e("Picasso", ex.toString()) + } + + val volleyQueue = Volley.newRequestQueue(baseContext) + + val jsonObjectRequest = + JsonObjectRequest("https://ponycule.equestria.horse/api/raindrops-two", + + { response -> + Log.i("HTTPRequest", response.toString()) + twoFronters = response!!.get("multiple") as Boolean + + if (twoFronters) { + val target = object : Target { + override fun onBitmapLoaded( + bitmap: Bitmap?, + from: Picasso.LoadedFrom? + ) { + try { + if (bitmap != null) { + bmp2 = bitmap + bmp2 = Bitmap.createScaledBitmap( + bmp2, + 36, + 36, true + ) + bmp2.prepareToDraw() + } + } catch (ex: IllegalArgumentException) { + Log.e("Picasso", ex.toString()) + } + } + + override fun onBitmapFailed( + e: Exception?, + errorDrawable: Drawable? + ) { + Log.e("Picasso", e.toString()) + } + + override fun onPrepareLoad(placeHolderDrawable: Drawable?) {} + } + + Picasso.get().load( + "https://ponycule.equestria.horse/api/raindrops-img2-round2" + ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) + } + }, + + { error -> + Log.e( + "HTTPRequest", + "Request error: ${error.localizedMessage}" + ) + }) + + volleyQueue.add(jsonObjectRequest) + } + + override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) { + Log.e("Picasso", e.toString()) + } + + override fun onPrepareLoad(placeHolderDrawable: Drawable?) {} + } + + Picasso.get().load( + "https://ponycule.equestria.horse/api/raindrops-img-round2" + ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) + } else { + if (showDate) { + if (twoFronters) { + canvas.drawBitmap(bmp2, mCenterX - 4f/2f, 0f, mBackgroundPaint) + canvas.drawBitmap(bmp, mCenterX - 88f/2f, 0f, mBackgroundPaint) + } else { + canvas.drawBitmap(bmp, mCenterX - 36f/2f, 0f, mBackgroundPaint) + } + } + } + } + + val paintOut2 = Paint().apply { + color = resources.getColor(R.color.bluey_bluey_circle) + style = Paint.Style.STROKE + strokeWidth = 15f + strokeCap = Paint.Cap.ROUND + isAntiAlias = true + setShadowLayer( + 1.5f, 0f, 0f, resources.getColor(R.color.cutiemark_shadow) + ) + } + + val seconds = + mCalendar.get(Calendar.SECOND) + mCalendar.get(Calendar.MILLISECOND) / 1000f + val secondsRotation = seconds * 6f + + val currentDayFetched = mCalendar.get(Calendar.DAY_OF_WEEK) - 1 + val currentHourFetched = mCalendar.get(Calendar.HOUR_OF_DAY) + + if (currentDayFetched > currentDay || currentDayFetched < currentDay) { + currentDay = currentDayFetched + initializeBackground() + initializeWatchFace() + } + + if (currentHourFetched > currentHour || currentHourFetched < currentHour) { + currentHour = currentHourFetched + initializeBackground() + initializeWatchFace() + } + + canvas.drawArc(10f, 10f, mCenterX * 2f - 10f, mCenterY * 2f - 10f, secondsRotation - 1f + 270f, 0.15f, false, paintOut2) + } + + override fun onVisibilityChanged(visible: Boolean) { + super.onVisibilityChanged(visible) + + if (visible) { + registerReceiver() + /* Update time zone in case it changed while we weren"t visible. */ + mCalendar.timeZone = TimeZone.getDefault() + invalidate() + } else { + showDate = false + unregisterReceiver() + } + + /* Check and trigger whether or not timer should be running (only in active mode). */ + updateTimer() + } + + private fun registerReceiver() { + if (mRegisteredTimeZoneReceiver) { + return + } + mRegisteredTimeZoneReceiver = true + val filter = IntentFilter(Intent.ACTION_TIMEZONE_CHANGED) + this@BlueyBlueyFace.registerReceiver(mTimeZoneReceiver, filter) + } + + private fun unregisterReceiver() { + if (!mRegisteredTimeZoneReceiver) { + return + } + mRegisteredTimeZoneReceiver = false + this@BlueyBlueyFace.unregisterReceiver(mTimeZoneReceiver) + } + + /** + * Starts/stops the [.mUpdateTimeHandler] timer based on the state of the watch face. + */ + private fun updateTimer() { + mUpdateTimeHandler.removeMessages(MSG_UPDATE_TIME) + if (shouldTimerBeRunning()) { + mUpdateTimeHandler.sendEmptyMessage(MSG_UPDATE_TIME) + } + } + + /** + * Returns whether the [.mUpdateTimeHandler] timer should be running. The timer + * should only run in active mode. + */ + private fun shouldTimerBeRunning(): Boolean { + return isVisible && !mAmbient + } + + /** + * Handle updating the time periodically in interactive mode. + */ + fun handleUpdateTimeMessage() { + invalidate() + if (shouldTimerBeRunning()) { + val timeMs = System.currentTimeMillis() + val delayMs = INTERACTIVE_UPDATE_RATE_MS - timeMs % INTERACTIVE_UPDATE_RATE_MS + mUpdateTimeHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs) + } + } + } +}
\ No newline at end of file diff --git a/app/src/main/java/dev/equestria/ponywatch/CutiemarkFace.kt b/app/src/main/java/dev/equestria/ponywatch/CutiemarkFace.kt index da876a6..ae5461a 100644 --- a/app/src/main/java/dev/equestria/ponywatch/CutiemarkFace.kt +++ b/app/src/main/java/dev/equestria/ponywatch/CutiemarkFace.kt @@ -494,7 +494,7 @@ class CutiemarkFace : CanvasWatchFaceService() { val volleyQueue = Volley.newRequestQueue(baseContext) - val jsonObjectRequest = JsonObjectRequest("https://ponies.equestria.horse/api/raindrops-two", + val jsonObjectRequest = JsonObjectRequest("https://ponycule.equestria.horse/api/raindrops-two", { response -> Log.i("HTTPRequest", response.toString()) @@ -525,7 +525,7 @@ class CutiemarkFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img2-round" + "https://ponycule.equestria.horse/api/raindrops-img2-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } }, @@ -543,7 +543,7 @@ class CutiemarkFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img-round" + "https://ponycule.equestria.horse/api/raindrops-img-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } else { if (twoFronters) { diff --git a/app/src/main/java/dev/equestria/ponywatch/FeathersFace.kt b/app/src/main/java/dev/equestria/ponywatch/FeathersFace.kt index 1d1ea55..ebb4fc2 100644 --- a/app/src/main/java/dev/equestria/ponywatch/FeathersFace.kt +++ b/app/src/main/java/dev/equestria/ponywatch/FeathersFace.kt @@ -375,7 +375,7 @@ class FeathersFace : CanvasWatchFaceService() { val volleyQueue = Volley.newRequestQueue(baseContext) val jsonObjectRequest = - JsonObjectRequest("https://ponies.equestria.horse/api/raindrops-two", + JsonObjectRequest("https://ponycule.equestria.horse/api/raindrops-two", { response -> Log.i("HTTPRequest", response.toString()) @@ -412,7 +412,7 @@ class FeathersFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img2-round" + "https://ponycule.equestria.horse/api/raindrops-img2-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } }, @@ -435,7 +435,7 @@ class FeathersFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img-round" + "https://ponycule.equestria.horse/api/raindrops-img-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } else { if (twoFronters) { diff --git a/app/src/main/java/dev/equestria/ponywatch/GlitterFace.kt b/app/src/main/java/dev/equestria/ponywatch/GlitterFace.kt index bf2ed58..f58d5c4 100644 --- a/app/src/main/java/dev/equestria/ponywatch/GlitterFace.kt +++ b/app/src/main/java/dev/equestria/ponywatch/GlitterFace.kt @@ -375,7 +375,7 @@ class GlitterFace : CanvasWatchFaceService() { val volleyQueue = Volley.newRequestQueue(baseContext) val jsonObjectRequest = - JsonObjectRequest("https://ponies.equestria.horse/api/raindrops-two", + JsonObjectRequest("https://ponycule.equestria.horse/api/raindrops-two", { response -> Log.i("HTTPRequest", response.toString()) @@ -412,7 +412,7 @@ class GlitterFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img2-round" + "https://ponycule.equestria.horse/api/raindrops-img2-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } }, @@ -435,7 +435,7 @@ class GlitterFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img-round" + "https://ponycule.equestria.horse/api/raindrops-img-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } else { if (twoFronters) { diff --git a/app/src/main/java/dev/equestria/ponywatch/UnitedFace.kt b/app/src/main/java/dev/equestria/ponywatch/UnitedFace.kt index 4749b0b..87c4a7b 100644 --- a/app/src/main/java/dev/equestria/ponywatch/UnitedFace.kt +++ b/app/src/main/java/dev/equestria/ponywatch/UnitedFace.kt @@ -468,7 +468,7 @@ class UnitedFace : CanvasWatchFaceService() { canvas.drawText("$it", canvas.width - 48f, (canvas.height / 2).toFloat() + 20f + 7f, paint) } - if (BuildConfig.ENABLE_PLURALITY || true) { + if (BuildConfig.ENABLE_PLURALITY) { if (mCalendar.get(Calendar.MINUTE) != lastRefreshMinute) { lastRefreshMinute = mCalendar.get(Calendar.MINUTE) @@ -495,7 +495,7 @@ class UnitedFace : CanvasWatchFaceService() { val volleyQueue = Volley.newRequestQueue(baseContext) val jsonObjectRequest = - JsonObjectRequest("https://ponies.equestria.horse/api/raindrops-two", + JsonObjectRequest("https://ponycule.equestria.horse/api/raindrops-two", { response -> Log.i("HTTPRequest", response.toString()) @@ -533,7 +533,7 @@ class UnitedFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img2-round2" + "https://ponycule.equestria.horse/api/raindrops-img2-round2" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } }, @@ -556,7 +556,7 @@ class UnitedFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img-round2" + "https://ponycule.equestria.horse/api/raindrops-img-round2" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } else { if (showDate) { diff --git a/app/src/main/java/dev/equestria/ponywatch/UnityFace.kt b/app/src/main/java/dev/equestria/ponywatch/UnityFace.kt index 0dc634f..09f5507 100644 --- a/app/src/main/java/dev/equestria/ponywatch/UnityFace.kt +++ b/app/src/main/java/dev/equestria/ponywatch/UnityFace.kt @@ -538,7 +538,7 @@ class UnityFace : CanvasWatchFaceService() { val volleyQueue = Volley.newRequestQueue(baseContext) val jsonObjectRequest = - JsonObjectRequest("https://ponies.equestria.horse/api/raindrops-two", + JsonObjectRequest("https://ponycule.equestria.horse/api/raindrops-two", { response -> Log.i("HTTPRequest", response.toString()) @@ -575,7 +575,7 @@ class UnityFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img2-round" + "https://ponycule.equestria.horse/api/raindrops-img2-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } }, @@ -598,7 +598,7 @@ class UnityFace : CanvasWatchFaceService() { } Picasso.get().load( - "https://ponies.equestria.horse/api/raindrops-img-round" + "https://ponycule.equestria.horse/api/raindrops-img-round" ).memoryPolicy(MemoryPolicy.NO_CACHE).into(target) } else { if (twoFronters) { diff --git a/app/src/main/res/drawable-nodpi/preview_bluey_bingo.png b/app/src/main/res/drawable-nodpi/preview_bluey_bingo.png Binary files differnew file mode 100644 index 0000000..4df225a --- /dev/null +++ b/app/src/main/res/drawable-nodpi/preview_bluey_bingo.png diff --git a/app/src/main/res/drawable-nodpi/preview_bluey_bluey.png b/app/src/main/res/drawable-nodpi/preview_bluey_bluey.png Binary files differnew file mode 100644 index 0000000..4beb66e --- /dev/null +++ b/app/src/main/res/drawable-nodpi/preview_bluey_bluey.png diff --git a/app/src/main/res/drawable-nodpi/watchface_bluey_bingo.png b/app/src/main/res/drawable-nodpi/watchface_bluey_bingo.png Binary files differnew file mode 100644 index 0000000..4a91c9f --- /dev/null +++ b/app/src/main/res/drawable-nodpi/watchface_bluey_bingo.png diff --git a/app/src/main/res/drawable-nodpi/watchface_bluey_bluey.png b/app/src/main/res/drawable-nodpi/watchface_bluey_bluey.png Binary files differnew file mode 100644 index 0000000..defb689 --- /dev/null +++ b/app/src/main/res/drawable-nodpi/watchface_bluey_bluey.png diff --git a/app/src/main/res/font/bluey_font.ttf b/app/src/main/res/font/bluey_font.ttf Binary files differnew file mode 100644 index 0000000..0ba0f96 --- /dev/null +++ b/app/src/main/res/font/bluey_font.ttf diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 1109144..ecacc70 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -59,4 +59,9 @@ <color name="united_text_5_1">#b3ebff</color> <color name="united_text_6_0">#ffdbe6</color> <color name="united_text_6_1">#e9bfff</color> + + <color name="bluey_bluey_text">#BFEDFF</color> + <color name="bluey_bluey_circle">#536D78</color> + <color name="bluey_bingo_text">#FFD9BF</color> + <color name="bluey_bingo_circle">#786253</color> </resources>
\ No newline at end of file diff --git a/build.gradle b/build.gradle index 9de7d04..d9f6c17 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.1.2' apply false - id 'com.android.library' version '8.1.2' apply false + id 'com.android.application' version '8.2.0' apply false + id 'com.android.library' version '8.2.0' apply false id 'org.jetbrains.kotlin.android' version '1.7.20' apply false }
\ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index edd2de2..7887531 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Jan 11 10:34:07 CET 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME |