@@ -9,18 +9,19 @@ import android.content.res.Configuration
99import android.graphics.Bitmap
1010import android.graphics.BitmapFactory
1111import android.graphics.drawable.BitmapDrawable
12+ import android.graphics.drawable.ColorDrawable
1213import android.net.Uri
1314import android.os.Build
1415import android.os.Bundle
1516import android.os.Environment
17+ import android.os.Handler
1618import android.provider.MediaStore
1719import android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback
1820import android.support.v4.content.FileProvider
21+ import android.support.v7.app.AlertDialog
1922import android.support.v7.app.AppCompatActivity
20- import android.view.Menu
21- import android.view.MenuItem
22- import android.view.MotionEvent
23- import android.view.View
23+ import android.view.*
24+ import android.widget.PopupMenu
2425import android.widget.Toast
2526import org.wordpress.android.util.AppLog
2627import org.wordpress.android.util.PermissionUtils
@@ -29,11 +30,14 @@ import org.wordpress.aztec.AztecText
2930import org.wordpress.aztec.picassoloader.PicassoImageLoader
3031import org.wordpress.aztec.source.SourceViewEditText
3132import org.wordpress.aztec.toolbar.AztecToolbar
32- import org.wordpress.aztec.toolbar.AztecToolbar.OnMediaOptionSelectedListener
33+ import org.wordpress.aztec.toolbar.AztecToolbarClickListener
34+ import org.xml.sax.Attributes
35+ import org.xml.sax.helpers.AttributesImpl
3336import java.io.File
3437
35- class MainActivity : AppCompatActivity (), OnMediaOptionSelectedListener, OnRequestPermissionsResultCallback,
36- View .OnTouchListener , AztecText .OnImeBackListener {
38+ class MainActivity : AppCompatActivity (), OnRequestPermissionsResultCallback, View.OnTouchListener,
39+ PopupMenu .OnMenuItemClickListener , AztecToolbarClickListener , AztecText .OnMediaTappedListener ,
40+ AztecText .OnImeBackListener {
3741 companion object {
3842 private val HEADING =
3943 " <h1>Heading 1</h1>" +
@@ -105,6 +109,11 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
105109 private lateinit var source: SourceViewEditText
106110 private lateinit var formattingToolbar: AztecToolbar
107111
112+ private var addPhotoMediaDialog: AlertDialog ? = null
113+ private var addVideoMediaDialog: AlertDialog ? = null
114+ private var mediaUploadDialog: AlertDialog ? = null
115+ private var mediaMenu: PopupMenu ? = null
116+
108117 private var mIsKeyboardOpen = false
109118 private var mHideActionBarOnSoftKeyboardUp = false
110119
@@ -127,13 +136,57 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
127136 }
128137 }
129138
130- val source = mediaPath // Temporary source value. Replace with URL after uploaded.
131- aztec.lineBlockFormatter.insertMedia(BitmapDrawable (resources, bitmap), source)
139+ insertMediaAndSimulateUpload(bitmap, mediaPath)
132140 }
133141
134142 super .onActivityResult(requestCode, resultCode, data)
135143 }
136144
145+ fun insertMediaAndSimulateUpload (bitmap : Bitmap ? , mediaPath : String ) {
146+ val id = (Math .random() * Int .MAX_VALUE ).toString()
147+
148+ val attrs = AttributesImpl ()
149+ attrs.addAttribute(" " , " src" , " src" , " string" , mediaPath) // Temporary source value. Replace with URL after uploaded.
150+ attrs.addAttribute(" " , " id" , " id" , " string" , id)
151+ attrs.addAttribute(" " , " uploading" , " uploading" , " string" , " true" )
152+
153+ aztec.insertMedia(BitmapDrawable (resources, bitmap), attrs)
154+
155+ val predicate = object : AztecText .AttributePredicate {
156+ override fun matches (attrs : Attributes ): Boolean {
157+ return attrs.getValue(" id" ) == id
158+ }
159+ }
160+
161+ aztec.setOverlay(predicate, 0 , ColorDrawable (0x80000000 .toInt()), Gravity .FILL , attrs)
162+ val progressDrawable = resources.getDrawable(android.R .drawable.progress_horizontal)
163+ // set the height of the progress bar to 2 (it's in dp since the drawable will be adjusted by the span)
164+ progressDrawable.setBounds(0 , 0 , 0 , 4 )
165+ aztec.setOverlay(predicate, 1 , progressDrawable, Gravity .FILL_HORIZONTAL or Gravity .TOP , attrs)
166+
167+ var progress = 0
168+
169+ // simulate an upload delay
170+ val runnable: Runnable = Runnable {
171+ aztec.setOverlayLevel(predicate, 1 , progress, attrs)
172+ aztec.refreshText()
173+ progress + = 2000
174+
175+ if (progress >= 10000 ) {
176+ attrs.removeAttribute(attrs.getIndex(" uploading" ))
177+ aztec.clearOverlays(predicate, attrs)
178+ }
179+ }
180+
181+ Handler ().post(runnable);
182+ Handler ().postDelayed(runnable, 2000 );
183+ Handler ().postDelayed(runnable, 4000 );
184+ Handler ().postDelayed(runnable, 6000 );
185+ Handler ().postDelayed(runnable, 8000 );
186+
187+ aztec.refreshText()
188+ }
189+
137190 override fun onCreate (savedInstanceState : Bundle ? ) {
138191 super .onCreate(savedInstanceState)
139192 setContentView(R .layout.activity_main)
@@ -153,7 +206,7 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
153206
154207 formattingToolbar = findViewById(R .id.formatting_toolbar) as AztecToolbar
155208 formattingToolbar.setEditor(aztec, source)
156- formattingToolbar.setMediaOptionSelectedListener (this )
209+ formattingToolbar.setToolbarListener (this )
157210
158211 // initialize the text & HTML
159212 source.displayStyledAndFormattedHtml(EXAMPLE )
@@ -165,6 +218,8 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
165218 aztec.setOnTouchListener(this )
166219 source.setOnImeBackListener(this )
167220 source.setOnTouchListener(this )
221+
222+ aztec.setOnMediaTappedListener(this )
168223 }
169224
170225 override fun onPause () {
@@ -192,6 +247,40 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
192247 }
193248 }
194249
250+ override fun onRestoreInstanceState (savedInstanceState : Bundle ? ) {
251+ super .onRestoreInstanceState(savedInstanceState)
252+
253+ savedInstanceState?.let {
254+ if (savedInstanceState.getBoolean(" isPhotoMediaDialogVisible" )) {
255+ showPhotoMediaDialog()
256+ }
257+
258+ if (savedInstanceState.getBoolean(" isVideoMediaDialogVisible" )) {
259+ showVideoMediaDialog()
260+ }
261+
262+ if (savedInstanceState.getBoolean(" isMediaUploadDialogVisible" )) {
263+ showMediaUploadDialog()
264+ }
265+ }
266+ }
267+
268+ override fun onSaveInstanceState (outState : Bundle ? ) {
269+ super .onSaveInstanceState(outState)
270+
271+ if (addPhotoMediaDialog != null && addPhotoMediaDialog!! .isShowing) {
272+ outState?.putBoolean(" isPhotoMediaDialogVisible" , true )
273+ }
274+
275+ if (addVideoMediaDialog != null && addVideoMediaDialog!! .isShowing) {
276+ outState?.putBoolean(" isVideoMediaDialogVisible" , true )
277+ }
278+
279+ if (mediaUploadDialog != null && mediaUploadDialog!! .isShowing) {
280+ outState?.putBoolean(" isMediaUploadDialogVisible" , true )
281+ }
282+ }
283+
195284 /* *
196285 * Returns true if a hardware keyboard is detected, otherwise false.
197286 */
@@ -278,7 +367,7 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
278367 return true
279368 }
280369
281- override fun onCameraPhotoMediaOptionSelected () {
370+ fun onCameraPhotoMediaOptionSelected () {
282371 if (PermissionUtils .checkAndRequestCameraAndStoragePermissions(this , MEDIA_CAMERA_PHOTO_PERMISSION_REQUEST_CODE )) {
283372 val intent = Intent (MediaStore .ACTION_IMAGE_CAPTURE )
284373
@@ -294,7 +383,7 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
294383 }
295384 }
296385
297- override fun onCameraVideoMediaOptionSelected () {
386+ fun onCameraVideoMediaOptionSelected () {
298387 if (PermissionUtils .checkAndRequestCameraAndStoragePermissions(this , MEDIA_CAMERA_PHOTO_PERMISSION_REQUEST_CODE )) {
299388 val intent = Intent (MediaStore .INTENT_ACTION_VIDEO_CAMERA )
300389
@@ -304,15 +393,15 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
304393 }
305394 }
306395
307- override fun onGalleryMediaOptionSelected () {
396+ fun onGalleryMediaOptionSelected () {
308397 Toast .makeText(this , " Launch gallery" , Toast .LENGTH_SHORT ).show()
309398 }
310399
311- override fun onPhotoLibraryMediaOptionSelected () {
400+ fun onPhotoLibraryMediaOptionSelected () {
312401 Toast .makeText(this , " Open library" , Toast .LENGTH_SHORT ).show()
313402 }
314403
315- override fun onPhotosMediaOptionSelected () {
404+ fun onPhotosMediaOptionSelected () {
316405 if (PermissionUtils .checkAndRequestStoragePermission(this , MEDIA_PHOTOS_PERMISSION_REQUEST_CODE )) {
317406 val intent: Intent
318407
@@ -334,11 +423,11 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
334423 }
335424 }
336425
337- override fun onVideoLibraryMediaOptionSelected () {
426+ fun onVideoLibraryMediaOptionSelected () {
338427 Toast .makeText(this , " Open library" , Toast .LENGTH_SHORT ).show()
339428 }
340429
341- override fun onVideosMediaOptionSelected () {
430+ fun onVideosMediaOptionSelected () {
342431 if (PermissionUtils .checkAndRequestStoragePermission(this , MEDIA_PHOTOS_PERMISSION_REQUEST_CODE )) {
343432 val intent: Intent
344433
@@ -431,4 +520,113 @@ class MainActivity : AppCompatActivity(), OnMediaOptionSelectedListener, OnReque
431520
432521 super .onRequestPermissionsResult(requestCode, permissions, grantResults)
433522 }
523+
524+ override fun onToolbarHtmlModeClicked () {
525+ val uploadingPredicate = object : AztecText .AttributePredicate {
526+ override fun matches (attrs : Attributes ): Boolean {
527+ return attrs.getIndex(" uploading" ) > - 1
528+ }
529+ }
530+
531+ val mediaPending = aztec.getAllMediaAttributes(uploadingPredicate).size > 0
532+
533+ if (mediaPending) {
534+ ToastUtils .showToast(this , R .string.media_upload_dialog_message)
535+ } else {
536+ formattingToolbar.toggleEditorMode()
537+ }
538+ }
539+
540+ override fun onToolbarAddMediaClicked () {
541+ mediaMenu = PopupMenu (this , formattingToolbar)
542+ mediaMenu?.setOnMenuItemClickListener(this )
543+ mediaMenu?.inflate(R .menu.media)
544+ mediaMenu?.show()
545+ }
546+
547+ override fun onMenuItemClick (item : MenuItem ? ): Boolean {
548+ item?.isChecked = (item?.isChecked == false )
549+
550+ when (item?.itemId) {
551+ org.wordpress.aztec.R .id.gallery -> {
552+ onGalleryMediaOptionSelected()
553+ return true
554+ }
555+ org.wordpress.aztec.R .id.photo -> {
556+ showPhotoMediaDialog()
557+ return true
558+ }
559+ org.wordpress.aztec.R .id.video -> {
560+ showVideoMediaDialog()
561+ return true
562+ }
563+ else -> return false
564+ }
565+ }
566+
567+ private fun showMediaUploadDialog () {
568+ val builder = AlertDialog .Builder (this )
569+ builder.setMessage(getString(org.wordpress.aztec.R .string.media_upload_dialog_message))
570+ builder.setPositiveButton(getString(org.wordpress.aztec.R .string.media_upload_dialog_positive), null )
571+ mediaUploadDialog = builder.create()
572+ mediaUploadDialog!! .show()
573+ }
574+
575+ private fun showPhotoMediaDialog () {
576+ val dialog = layoutInflater.inflate(R .layout.dialog_photo_media, null )
577+
578+ val camera = dialog.findViewById(org.wordpress.aztec.R .id.media_camera)
579+ camera.setOnClickListener({
580+ onCameraPhotoMediaOptionSelected()
581+ addPhotoMediaDialog?.dismiss()
582+ })
583+
584+ val photos = dialog.findViewById(org.wordpress.aztec.R .id.media_photos)
585+ photos.setOnClickListener({
586+ onPhotosMediaOptionSelected()
587+ addPhotoMediaDialog?.dismiss()
588+ })
589+
590+ val library = dialog.findViewById(org.wordpress.aztec.R .id.media_library)
591+ library.setOnClickListener({
592+ onPhotoLibraryMediaOptionSelected()
593+ addPhotoMediaDialog?.dismiss()
594+ })
595+
596+ val builder = AlertDialog .Builder (this )
597+ builder.setView(dialog)
598+ addPhotoMediaDialog = builder.create()
599+ addPhotoMediaDialog!! .show()
600+ }
601+
602+ private fun showVideoMediaDialog () {
603+ val dialog = layoutInflater.inflate(org.wordpress.aztec.R .layout.dialog_video_media, null )
604+
605+ val camera = dialog.findViewById(org.wordpress.aztec.R .id.media_camera)
606+ camera.setOnClickListener({
607+ onCameraVideoMediaOptionSelected()
608+ addVideoMediaDialog?.dismiss()
609+ })
610+
611+ val videos = dialog.findViewById(org.wordpress.aztec.R .id.media_videos)
612+ videos.setOnClickListener({
613+ onVideosMediaOptionSelected()
614+ addVideoMediaDialog?.dismiss()
615+ })
616+
617+ val library = dialog.findViewById(org.wordpress.aztec.R .id.media_library)
618+ library.setOnClickListener({
619+ onVideoLibraryMediaOptionSelected()
620+ addVideoMediaDialog?.dismiss()
621+ })
622+
623+ val builder = AlertDialog .Builder (this )
624+ builder.setView(dialog)
625+ addVideoMediaDialog = builder.create()
626+ addVideoMediaDialog!! .show()
627+ }
628+
629+ override fun mediaTapped (attrs : Attributes ? , naturalWidth : Int , naturalHeight : Int ) {
630+ ToastUtils .showToast(this , " Media tapped!" )
631+ }
434632}
0 commit comments