2020-08-07 09:21:14 +02:00
/ * Copyright ( C ) 2015 - 2020 abettenburg , Andreas Shimokawa , Carsten Pfeiffer ,
Daniele Gobbetti , Lem Dulfo
This file is part of Gadgetbridge .
Gadgetbridge is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Gadgetbridge is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities ;
2020-08-14 22:48:03 +02:00
import android.annotation.SuppressLint ;
2020-08-16 20:45:03 +02:00
import android.content.Context ;
2020-08-07 09:21:14 +02:00
import android.content.Intent ;
2020-08-16 20:45:03 +02:00
import android.content.res.Resources ;
2020-08-10 10:56:54 +02:00
import android.graphics.Typeface ;
2020-08-07 09:21:14 +02:00
import android.os.Bundle ;
2020-08-16 20:45:03 +02:00
import android.util.TypedValue ;
2020-08-10 10:56:54 +02:00
import android.view.Gravity ;
2020-08-15 14:45:43 +02:00
import android.view.MenuItem ;
2020-08-07 09:21:14 +02:00
import android.view.View ;
2020-08-14 22:48:03 +02:00
import android.view.animation.Animation ;
import android.view.animation.AnimationUtils ;
2020-08-07 09:21:14 +02:00
import android.widget.Button ;
import android.widget.ImageView ;
2020-08-14 22:48:03 +02:00
import android.widget.RelativeLayout ;
2020-08-10 10:56:54 +02:00
import android.widget.TableLayout ;
import android.widget.TableRow ;
2020-08-07 09:21:14 +02:00
import android.widget.TextView ;
import android.widget.Toast ;
2020-08-09 13:11:10 +02:00
import org.json.JSONArray ;
2020-08-08 16:22:55 +02:00
import org.json.JSONException ;
import org.json.JSONObject ;
2020-08-07 09:21:14 +02:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import java.io.IOException ;
2020-08-08 16:22:55 +02:00
import java.text.DecimalFormat ;
2020-08-09 13:11:10 +02:00
import java.util.Date ;
2020-08-08 16:22:55 +02:00
import java.util.Iterator ;
2020-08-07 09:21:14 +02:00
import java.util.concurrent.TimeUnit ;
import nodomain.freeyourgadget.gadgetbridge.R ;
2020-08-14 22:48:03 +02:00
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary ;
2020-08-07 09:21:14 +02:00
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice ;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind ;
2020-08-14 22:48:03 +02:00
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryItems ;
2020-08-20 09:03:26 +02:00
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryJsonSummary ;
2020-08-07 09:21:14 +02:00
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils ;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils ;
import nodomain.freeyourgadget.gadgetbridge.util.GB ;
2020-08-14 22:48:03 +02:00
import nodomain.freeyourgadget.gadgetbridge.util.SwipeEvents ;
2020-08-07 09:21:14 +02:00
public class ActivitySummaryDetail extends AbstractGBActivity {
private static final Logger LOG = LoggerFactory . getLogger ( ActivitySummaryDetail . class ) ;
2020-08-20 09:03:26 +02:00
2020-08-10 21:44:04 +02:00
private boolean show_raw_data = false ;
2020-08-14 22:48:03 +02:00
BaseActivitySummary currentItem = null ;
2020-08-16 20:45:03 +02:00
private int alternateColor ;
2020-08-18 11:16:36 +02:00
//private Object BottomSheetBehavior;
2020-08-07 09:21:14 +02:00
2020-08-14 22:48:03 +02:00
@SuppressLint ( " ClickableViewAccessibility " )
2020-08-07 09:21:14 +02:00
@Override
protected void onCreate ( Bundle savedInstanceState ) {
super . onCreate ( savedInstanceState ) ;
setContentView ( R . layout . activity_summary_details ) ;
Intent intent = getIntent ( ) ;
2020-08-18 10:39:44 +02:00
GBDevice gbDevice = intent . getParcelableExtra ( GBDevice . EXTRA_DEVICE ) ;
final int filter = intent . getIntExtra ( " filter " , 0 ) ;
final int position = intent . getIntExtra ( " position " , 0 ) ;
2020-08-18 11:16:36 +02:00
final long dateFromFilter = intent . getLongExtra ( " dateFromFilter " , 0 ) ;
final long dateToFilter = intent . getLongExtra ( " dateToFilter " , 0 ) ;
final ActivitySummaryItems items = new ActivitySummaryItems ( this , gbDevice , filter , dateFromFilter , dateToFilter ) ;
2020-08-14 22:48:03 +02:00
final RelativeLayout layout = findViewById ( R . id . activity_summary_detail_relative_layout ) ;
2020-08-16 20:45:03 +02:00
alternateColor = getAlternateColor ( this ) ;
2020-08-14 22:48:03 +02:00
2020-08-15 12:12:06 +02:00
final Animation animFadeRight ;
final Animation animFadeLeft ;
final Animation animBounceLeft ;
final Animation animBounceRight ;
animFadeRight = AnimationUtils . loadAnimation (
2020-08-14 22:48:03 +02:00
this ,
R . anim . flyright ) ;
2020-08-15 12:12:06 +02:00
animFadeLeft = AnimationUtils . loadAnimation (
2020-08-14 22:48:03 +02:00
this ,
R . anim . flyleft ) ;
2020-08-15 12:12:06 +02:00
animBounceLeft = AnimationUtils . loadAnimation (
this ,
R . anim . bounceleft ) ;
animBounceRight = AnimationUtils . loadAnimation (
this ,
R . anim . bounceright ) ;
2020-08-14 22:48:03 +02:00
layout . setOnTouchListener ( new SwipeEvents ( this ) {
@Override
public void onSwipeRight ( ) {
currentItem = items . getNextItem ( ) ;
if ( currentItem ! = null ) {
makeSummaryHeader ( currentItem ) ;
makeSummaryContent ( currentItem ) ;
2020-08-15 12:12:06 +02:00
layout . startAnimation ( animFadeRight ) ;
2020-08-14 22:48:03 +02:00
} else {
2020-08-15 12:12:06 +02:00
layout . startAnimation ( animBounceRight ) ;
2020-08-14 22:48:03 +02:00
}
}
@Override
public void onSwipeLeft ( ) {
currentItem = items . getPrevItem ( ) ;
if ( currentItem ! = null ) {
makeSummaryHeader ( currentItem ) ;
makeSummaryContent ( currentItem ) ;
2020-08-15 12:12:06 +02:00
layout . startAnimation ( animFadeLeft ) ;
2020-08-14 22:48:03 +02:00
} else {
2020-08-15 12:12:06 +02:00
layout . startAnimation ( animBounceLeft ) ;
2020-08-14 22:48:03 +02:00
}
}
} ) ;
currentItem = items . getItem ( position ) ;
if ( currentItem ! = null ) {
makeSummaryHeader ( currentItem ) ;
makeSummaryContent ( currentItem ) ;
}
//allows long-press.switch of data being in raw form or recalculated
2020-08-18 10:39:44 +02:00
ImageView activity_icon = findViewById ( R . id . item_image ) ;
2020-08-14 22:48:03 +02:00
activity_icon . setOnLongClickListener ( new View . OnLongClickListener ( ) {
public boolean onLongClick ( View v ) {
show_raw_data = ! show_raw_data ;
if ( currentItem ! = null ) {
makeSummaryHeader ( currentItem ) ;
makeSummaryContent ( currentItem ) ;
}
return false ;
}
} ) ;
2020-08-07 09:21:14 +02:00
2020-08-14 22:48:03 +02:00
}
private void makeSummaryHeader ( BaseActivitySummary item ) {
//make view of data from main part of item
final String gpxTrack = item . getGpxTrack ( ) ;
2020-08-18 10:39:44 +02:00
Button show_track_btn = findViewById ( R . id . showTrack ) ;
2020-08-07 09:21:14 +02:00
show_track_btn . setVisibility ( View . GONE ) ;
if ( gpxTrack ! = null ) {
show_track_btn . setVisibility ( View . VISIBLE ) ;
show_track_btn . setOnClickListener ( new View . OnClickListener ( ) {
public void onClick ( View v ) {
try {
2020-08-09 01:40:59 +02:00
AndroidUtils . viewFile ( gpxTrack , Intent . ACTION_VIEW , ActivitySummaryDetail . this ) ;
2020-08-07 09:21:14 +02:00
} catch ( IOException e ) {
GB . toast ( getApplicationContext ( ) , " Unable to display GPX track: " + e . getMessage ( ) , Toast . LENGTH_LONG , GB . ERROR , e ) ;
}
}
} ) ;
}
2020-08-14 22:48:03 +02:00
String activitykindname = ActivityKind . asString ( item . getActivityKind ( ) , getApplicationContext ( ) ) ;
2020-08-18 10:39:44 +02:00
Date starttime = item . getStartTime ( ) ;
Date endtime = item . getEndTime ( ) ;
2020-08-09 13:11:10 +02:00
String starttimeS = DateTimeUtils . formatDateTime ( starttime ) ;
String endtimeS = DateTimeUtils . formatDateTime ( endtime ) ;
String durationhms = DateTimeUtils . formatDurationHoursMinutes ( ( endtime . getTime ( ) - starttime . getTime ( ) ) , TimeUnit . MILLISECONDS ) ;
2020-08-07 09:21:14 +02:00
2020-08-18 10:39:44 +02:00
ImageView activity_icon = findViewById ( R . id . item_image ) ;
2020-08-14 22:48:03 +02:00
activity_icon . setImageResource ( ActivityKind . getIconId ( item . getActivityKind ( ) ) ) ;
2020-08-18 10:39:44 +02:00
TextView activity_kind = findViewById ( R . id . activitykind ) ;
2020-08-09 13:11:10 +02:00
activity_kind . setText ( activitykindname ) ;
2020-08-18 10:39:44 +02:00
TextView start_time = findViewById ( R . id . starttime ) ;
2020-08-09 13:11:10 +02:00
start_time . setText ( starttimeS ) ;
2020-08-18 10:39:44 +02:00
TextView end_time = findViewById ( R . id . endtime ) ;
2020-08-09 13:11:10 +02:00
end_time . setText ( endtimeS ) ;
2020-08-18 10:39:44 +02:00
TextView activity_duration = findViewById ( R . id . duration ) ;
2020-08-07 09:21:14 +02:00
activity_duration . setText ( durationhms ) ;
2020-08-08 16:22:55 +02:00
2020-08-14 22:48:03 +02:00
}
2020-08-18 10:39:44 +02:00
private void makeSummaryContent ( BaseActivitySummary item ) {
2020-08-14 22:48:03 +02:00
//make view of data from summaryData of item
TableLayout fieldLayout = findViewById ( R . id . summaryDetails ) ;
fieldLayout . removeAllViews ( ) ; //remove old widgets
2020-08-20 09:03:26 +02:00
ActivitySummaryJsonSummary activitySummaryJsonSummary = new ActivitySummaryJsonSummary ( item ) ;
//JSONObject summarySubdata = activitySummaryJsonSummary.getSummaryData();
JSONObject data = activitySummaryJsonSummary . getSummaryGroupedList ( ) ; //get list, grouped by groups
if ( data = = null ) return ;
2020-08-10 21:44:04 +02:00
2020-08-09 13:11:10 +02:00
Iterator < String > keys = data . keys ( ) ;
DecimalFormat df = new DecimalFormat ( " #.## " ) ;
while ( keys . hasNext ( ) ) {
String key = keys . next ( ) ;
try {
LOG . error ( " SportsActivity: " + key + " : " + data . get ( key ) + " \ n " ) ;
JSONArray innerList = ( JSONArray ) data . get ( key ) ;
2020-08-10 10:56:54 +02:00
TableRow label_row = new TableRow ( ActivitySummaryDetail . this ) ;
TextView label_field = new TextView ( ActivitySummaryDetail . this ) ;
label_field . setTextSize ( 16 ) ;
label_field . setTypeface ( null , Typeface . BOLD ) ;
label_field . setText ( String . format ( " %s " , getStringResourceByName ( key ) ) ) ;
label_row . addView ( label_field ) ;
fieldLayout . addView ( label_row ) ;
2020-08-09 13:11:10 +02:00
for ( int i = 0 ; i < innerList . length ( ) ; i + + ) {
2020-08-20 22:27:33 +02:00
TextView name_field = new TextView ( ActivitySummaryDetail . this ) ;
TextView value_field = new TextView ( ActivitySummaryDetail . this ) ;
name_field . setGravity ( Gravity . START ) ;
value_field . setGravity ( Gravity . END ) ;
2020-08-09 13:11:10 +02:00
JSONObject innerData = innerList . getJSONObject ( i ) ;
2020-08-20 22:27:33 +02:00
String unit = innerData . getString ( " unit " ) ;
2020-08-09 13:11:10 +02:00
String name = innerData . getString ( " name " ) ;
2020-08-20 22:27:33 +02:00
if ( ! unit . equals ( " string " ) ) {
double value = innerData . getDouble ( " value " ) ;
if ( ! show_raw_data ) {
//special casing here:
switch ( unit ) {
case " meters_second " :
value = value * 3 . 6 ;
unit = " km_h " ;
break ;
case " seconds_m " :
value = 3 . 6 / value ;
unit = " minutes_km " ;
break ;
case " seconds_km " :
value = value / 60 ;
unit = " minutes_km " ;
break ;
}
}
2020-08-09 13:11:10 +02:00
2020-08-20 22:27:33 +02:00
if ( unit . equals ( " seconds " ) & & ! show_raw_data ) { //rather then plain seconds, show formatted duration
value_field . setText ( DateTimeUtils . formatDurationHoursMinutes ( ( long ) value , TimeUnit . SECONDS ) ) ;
} else {
value_field . setText ( String . format ( " %s %s " , df . format ( value ) , getStringResourceByName ( unit ) ) ) ;
2020-08-10 21:44:04 +02:00
}
2020-08-20 22:27:33 +02:00
} else {
2020-08-22 10:31:32 +02:00
value_field . setText ( getStringResourceByName ( innerData . getString ( " value " ) ) ) ; //we could optimize here a bit and only do this for particular activities (swim at the moment...)
2020-08-09 13:11:10 +02:00
}
2020-08-20 22:27:33 +02:00
2020-08-10 10:56:54 +02:00
TableRow field_row = new TableRow ( ActivitySummaryDetail . this ) ;
2020-08-16 20:45:03 +02:00
if ( i % 2 = = 0 ) field_row . setBackgroundColor ( alternateColor ) ;
2020-08-10 14:55:57 +02:00
2020-08-10 10:56:54 +02:00
name_field . setText ( getStringResourceByName ( name ) ) ;
2020-08-10 14:55:57 +02:00
TableRow . LayoutParams params = new TableRow . LayoutParams ( 0 , TableRow . LayoutParams . WRAP_CONTENT , 1f ) ;
value_field . setLayoutParams ( params ) ;
2020-08-10 10:56:54 +02:00
field_row . addView ( name_field ) ;
field_row . addView ( value_field ) ;
fieldLayout . addView ( field_row ) ;
2020-08-09 13:11:10 +02:00
}
} catch ( JSONException e ) {
LOG . error ( " SportsActivity " , e ) ;
}
}
2020-08-10 10:56:54 +02:00
}
2020-08-09 13:11:10 +02:00
2020-08-08 16:22:55 +02:00
2020-08-09 13:11:10 +02:00
2020-08-16 20:45:03 +02:00
public static int getAlternateColor ( Context context ) {
TypedValue typedValue = new TypedValue ( ) ;
Resources . Theme theme = context . getTheme ( ) ;
theme . resolveAttribute ( R . attr . alternate_row_background , typedValue , true ) ;
return typedValue . data ;
}
2020-08-07 09:21:14 +02:00
2020-08-09 13:11:10 +02:00
private String getStringResourceByName ( String aString ) {
String packageName = getPackageName ( ) ;
int resId = getResources ( ) . getIdentifier ( aString , " string " , packageName ) ;
if ( resId = = 0 ) {
2020-08-22 10:31:32 +02:00
//LOG.warn("SportsActivity " + "Missing string in strings:" + aString);
2020-08-09 13:11:10 +02:00
return aString ;
} else {
return getString ( resId ) ;
}
}
2020-08-07 09:21:14 +02:00
2020-08-15 14:45:43 +02:00
@Override
public boolean onOptionsItemSelected ( MenuItem item ) {
switch ( item . getItemId ( ) ) {
case android . R . id . home :
// back button
finish ( ) ;
return true ;
}
return super . onOptionsItemSelected ( item ) ;
}
2020-08-07 09:21:14 +02:00
}