Project

General

Profile

Download (18.4 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / main / MainActivity.java @ 88913ad4

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.main;
11

    
12
import android.content.Intent;
13
import android.content.SharedPreferences;
14
import android.content.pm.PackageInfo;
15
import android.content.pm.PackageManager;
16
import android.content.res.Configuration;
17
import android.os.Build;
18
import android.os.Bundle;
19
import android.util.DisplayMetrics;
20
import android.util.TypedValue;
21
import android.view.DisplayCutout;
22
import android.view.View;
23
import android.view.ViewGroup;
24
import android.view.WindowManager;
25
import android.widget.LinearLayout;
26
import android.widget.ScrollView;
27
import android.widget.TextView;
28

    
29
import androidx.annotation.NonNull;
30
import androidx.appcompat.app.AppCompatActivity;
31
import androidx.preference.PreferenceManager;
32

    
33
import com.google.firebase.analytics.FirebaseAnalytics;
34
import com.google.firebase.inappmessaging.FirebaseInAppMessaging;
35

    
36
import org.distorted.bandaged.BandagedActivity;
37
import org.distorted.config.ConfigActivity;
38
import org.distorted.info.InfoActivity;
39
import org.distorted.dialogs.RubikDialogAbout;
40
import org.distorted.dialogs.RubikDialogCreators;
41
import org.distorted.dialogs.RubikDialogExit;
42
import org.distorted.dialogs.RubikDialogScores;
43
import org.distorted.dialogs.RubikDialogUpdates;
44
import org.distorted.external.RubikNetwork;
45
import org.distorted.external.RubikScores;
46
import org.distorted.external.RubikUpdates;
47
import org.distorted.messaging.RubikInAppMessanging;
48
import org.distorted.objects.RubikObject;
49
import org.distorted.objects.RubikObjectList;
50
import org.distorted.patternui.PatternActivity;
51
import org.distorted.playui.PlayActivity;
52
import org.distorted.solverui.SolverActivity;
53
import org.distorted.tutorials.TutorialActivity;
54

    
55
///////////////////////////////////////////////////////////////////////////////////////////////////
56

    
57
public class MainActivity extends AppCompatActivity implements RubikNetwork.Updatee, RubikDialogScores.ScoresInvoker
58
{
59
    public static final float RATIO_BAR = 0.080f;
60
    public static final int FLAGS =  View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
61
                                   | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
62
                                   | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
63
                                   | View.SYSTEM_UI_FLAG_FULLSCREEN
64
                                   | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
65

    
66
    private boolean mJustStarted;
67
    private FirebaseAnalytics mFirebaseAnalytics;
68
    private int mCurrentApiVersion;
69
    private String mOldVersion, mCurrVersion;
70
    private int mScreenWidth, mScreenHeight;
71
    private TextView mBubbleUpdates;
72
    private int mNumUpdates;
73
    private int mCurrentObject;
74
    private MainScrollGrid mGrid;
75
    private int mSortMode;
76

    
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78

    
79
    @Override
80
    protected void onCreate(Bundle savedState)
81
      {
82
      super.onCreate(savedState);
83
      setTheme(R.style.MaterialThemeNoActionBar);
84
      setContentView(R.layout.main);
85
      hideNavigationBar();
86

    
87
      mCurrentObject = 0;
88
      mJustStarted = true;
89
      mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
90

    
91
      cutoutHack();
92
      computeHeights();
93

    
94
      mCurrVersion = getAppVers();
95

    
96
      mBubbleUpdates = findViewById(R.id.bubbleUpdates);
97
      mBubbleUpdates.setVisibility(View.INVISIBLE);
98
      mNumUpdates = 0;
99

    
100
      Thread thread = new Thread()
101
        {
102
        public void run()
103
          {
104
          RubikInAppMessanging listener = new RubikInAppMessanging();
105
          FirebaseInAppMessaging.getInstance().addClickListener(listener);
106
          }
107
        };
108

    
109
      thread.start();
110
      }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
// this does not include possible insets
114

    
115
    private void computeHeights()
116
      {
117
      LinearLayout.LayoutParams pU = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, RATIO_BAR);
118
      LinearLayout layoutTop = findViewById(R.id.upperBar);
119
      layoutTop.setLayoutParams(pU);
120

    
121
      LinearLayout.LayoutParams pS = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1-2*RATIO_BAR);
122
      ScrollView scroll = findViewById(R.id.objectScroll);
123
      scroll.setLayoutParams(pS);
124

    
125
      LinearLayout.LayoutParams pL = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, RATIO_BAR);
126
      LinearLayout layoutBot = findViewById(R.id.lowerBar);
127
      layoutBot.setLayoutParams(pL);
128
      }
129

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

    
132
    private void hideNavigationBar()
133
      {
134
      mCurrentApiVersion = Build.VERSION.SDK_INT;
135

    
136
      if(mCurrentApiVersion >= Build.VERSION_CODES.KITKAT)
137
        {
138
        final View decorView = getWindow().getDecorView();
139

    
140
        decorView.setSystemUiVisibility(FLAGS);
141

    
142
        decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener()
143
          {
144
          @Override
145
          public void onSystemUiVisibilityChange(int visibility)
146
            {
147
            if((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0)
148
              {
149
              decorView.setSystemUiVisibility(FLAGS);
150
              }
151
            }
152
          });
153
        }
154
      }
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

    
158
    @Override
159
    public void onAttachedToWindow()
160
      {
161
      super.onAttachedToWindow();
162

    
163
      getWindowWidth(getResources().getConfiguration());
164
      mGrid = new MainScrollGrid();
165
      mGrid.createGrid(this,mScreenWidth,mSortMode);
166

    
167
      if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.P )
168
        {
169
        DisplayCutout cutout = getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
170
        int insetHeight = cutout!=null ? cutout.getSafeInsetTop() : 0;
171

    
172
        if( insetHeight>0 )
173
          {
174
          LinearLayout.LayoutParams pH = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, RATIO_BAR);
175
          LinearLayout layoutHid = findViewById(R.id.hiddenBar);
176
          layoutHid.setLayoutParams(pH);
177

    
178
          LinearLayout.LayoutParams pS = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1-3*RATIO_BAR);
179
          ScrollView scroll = findViewById(R.id.objectScroll);
180
          scroll.setLayoutParams(pS);
181
          }
182
        }
183
      }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186
// do not avoid cutouts
187

    
188
    private void cutoutHack()
189
      {
190
      if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.P )
191
        {
192
        getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
193
        }
194
      }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
    private void getWindowWidth(Configuration conf)
199
      {
200
      int dpi = getResources().getDisplayMetrics().densityDpi;
201
      float conv = ((float) dpi/DisplayMetrics.DENSITY_DEFAULT);
202

    
203
      mScreenWidth = (int) (conf.screenWidthDp*conv + 0.5f);
204
      mScreenHeight= (int) (conf.screenHeightDp*conv + 0.5f);
205
      }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
    @Override
210
    public void onWindowFocusChanged(boolean hasFocus)
211
      {
212
      super.onWindowFocusChanged(hasFocus);
213

    
214
      if( mCurrentApiVersion >= Build.VERSION_CODES.KITKAT && hasFocus )
215
        {
216
        getWindow().getDecorView().setSystemUiVisibility(FLAGS);
217
        }
218
      }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
    @Override
223
    public void onConfigurationChanged(@NonNull Configuration conf)
224
      {
225
      super.onConfigurationChanged(conf);
226

    
227
      getWindowWidth(conf);
228
      if( mGrid!=null ) mGrid.updateGrid(this,mScreenWidth);
229
      }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232
    
233
    @Override
234
    protected void onPause() 
235
      {
236
      super.onPause();
237
      RubikNetwork.onPause();
238
      savePreferences();
239
      }
240

    
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242
    
243
    @Override
244
    protected void onResume() 
245
      {
246
      super.onResume();
247

    
248
      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
249
      restorePreferences(preferences,mJustStarted);
250

    
251
      RubikNetwork network = RubikNetwork.getInstance();
252
      network.signUpForUpdates(this);
253

    
254
      if( mJustStarted )
255
        {
256
        mJustStarted = false;
257

    
258
        network.downloadUpdates(this);
259
        RubikScores scores = RubikScores.getInstance();
260
        scores.incrementNumRuns();
261
        scores.setCountry(this);
262
        }
263

    
264
      if( !mOldVersion.equals(mCurrVersion) ) displayNovelties();
265
      }
266

    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268

    
269
    private void displayNovelties()
270
      {
271
      Bundle bundle = new Bundle();
272
      bundle.putString("argument",mOldVersion);
273
      RubikDialogAbout newDialog = new RubikDialogAbout();
274
      newDialog.setArguments(bundle);
275
      newDialog.show(getSupportFragmentManager(), RubikDialogAbout.getDialogTag() );
276
      }
277

    
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279
    
280
    @Override
281
    protected void onDestroy() 
282
      {
283
      super.onDestroy();
284
      }
285

    
286
///////////////////////////////////////////////////////////////////////////////////////////////////
287

    
288
    private String getAppVers()
289
      {
290
      try
291
        {
292
        PackageInfo pInfo = getPackageManager().getPackageInfo( getPackageName(), 0);
293
        return pInfo.versionName;
294
        }
295
      catch( PackageManager.NameNotFoundException e )
296
        {
297
        return "unknown";
298
        }
299
      }
300

    
301
///////////////////////////////////////////////////////////////////////////////////////////////////
302

    
303
    private void savePreferences()
304
      {
305
      SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
306
      SharedPreferences.Editor editor = preferences.edit();
307

    
308
      editor.putString("appVersion", mCurrVersion );
309
      editor.putInt("sortMode", mSortMode);
310

    
311
      RubikObjectList.savePreferences(editor);
312

    
313
      boolean success = editor.commit();
314
      if( !success ) android.util.Log.e("D", "Failed to save preferences");
315
      }
316

    
317
///////////////////////////////////////////////////////////////////////////////////////////////////
318

    
319
    private void restorePreferences(SharedPreferences preferences, boolean justStarted)
320
      {
321
      mOldVersion = preferences.getString("appVersion","");
322
      mSortMode = preferences.getInt("sortMode", MainSettingsPopup.SORT_DEFAULT);
323

    
324
      RubikObjectList.restorePreferences(this,preferences,justStarted);
325
      RubikScores scores = RubikScores.getInstance();
326
      scores.restorePreferences(preferences);
327

    
328
      if( scores.isVerified() )
329
        {
330
        FirebaseAnalytics analytics = getAnalytics();
331
        analytics.setUserId(scores.getName());
332
        }
333
      }
334

    
335
///////////////////////////////////////////////////////////////////////////////////////////////////
336

    
337
    private void updateBubble(int num)
338
      {
339
      runOnUiThread(new Runnable()
340
        {
341
        @Override
342
        public void run()
343
          {
344
          mNumUpdates = num;
345

    
346
          if( num>0 )
347
            {
348
            String shownNum = String.valueOf(num);
349
            mBubbleUpdates.setText(shownNum);
350
            mBubbleUpdates.setVisibility(View.VISIBLE);
351
            int height = (int)(0.05f*mScreenWidth);
352
            mBubbleUpdates.setTextSize(TypedValue.COMPLEX_UNIT_PX,height);
353
            }
354
          else
355
            {
356
            mBubbleUpdates.setVisibility(View.INVISIBLE);
357
            }
358
          }
359
        });
360
      }
361

    
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363
// PUBLIC API
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

    
366
    public FirebaseAnalytics getAnalytics()
367
      {
368
      return mFirebaseAnalytics;
369
      }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
    public int getObjectOrdinal()
374
      {
375
      return mCurrentObject;
376
      }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
    public void setCurrentObject(int current)
381
      {
382
      mCurrentObject = current;
383
      }
384

    
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386

    
387
    public void switchToTutorial(int objectOrdinal)
388
      {
389
      Intent intent = new Intent(this, TutorialActivity.class);
390
      intent.putExtra("obj", objectOrdinal);
391
      startActivity(intent);
392
      }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
    public void switchToInfo(int objectOrdinal)
397
      {
398
      Intent intent = new Intent(this, InfoActivity.class);
399
      intent.putExtra("obj", objectOrdinal);
400
      startActivity(intent);
401
      }
402

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

    
405
    public void switchToConfig(int objectOrdinal)
406
      {
407
      Intent intent = new Intent(this, ConfigActivity.class);
408
      intent.putExtra("obj", objectOrdinal);
409
      startActivity(intent);
410
      }
411

    
412
///////////////////////////////////////////////////////////////////////////////////////////////////
413

    
414
    public void switchToBandagedCreator(int objectOrdinal)
415
      {
416
      Intent intent = new Intent(this, BandagedActivity.class);
417
      intent.putExtra("obj", objectOrdinal);
418
      startActivity(intent);
419
      }
420

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422

    
423
    public void switchToSolver(int objectOrdinal)
424
      {
425
      Intent intent = new Intent(this, SolverActivity.class);
426
      intent.putExtra("obj", objectOrdinal);
427
      startActivity(intent);
428
      }
429

    
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431

    
432
    public void switchToPattern(int objectOrdinal)
433
      {
434
      Intent intent = new Intent(this, PatternActivity.class);
435
      intent.putExtra("obj", objectOrdinal);
436
      startActivity(intent);
437
      }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440

    
441
    public void switchToPlay(RubikObject object, int ordinal, int scrambles, int level)
442
      {
443
      boolean local = object.isLocal();
444
      String name = local ? object.getLowerName() : object.getUpperName();
445

    
446
      Intent intent = new Intent(this, PlayActivity.class);
447
      intent.putExtra("level", level);
448
      intent.putExtra("name", name );
449
      intent.putExtra("scrambles", scrambles);
450
      intent.putExtra("local", local );
451
      intent.putExtra("ordinal", ordinal );
452
      startActivity(intent);
453
      }
454

    
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

    
457
    public void onScores(View v)
458
      {
459
      Bundle sBundle = new Bundle();
460
      sBundle.putString("argument", "false");
461
      RubikDialogScores scores = new RubikDialogScores();
462
      scores.setArguments(sBundle);
463
      scores.show(getSupportFragmentManager(), null);
464
      }
465

    
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467

    
468
    public void onSettings(View v)
469
      {
470
      int sw = (int)(mScreenWidth*0.7);
471
      int sh = (int)(mScreenHeight*0.2f);
472

    
473
      int vw = v.getWidth();
474

    
475
      MainSettingsPopup popup = new MainSettingsPopup(this,mSortMode,mScreenWidth,mScreenHeight);
476
      popup.displayPopup(this,v,sw,sh,(int)((vw-sw)/2),0);
477
      }
478

    
479
///////////////////////////////////////////////////////////////////////////////////////////////////
480

    
481
    public void onUpdates(View v)
482
      {
483
      RubikDialogUpdates diag = new RubikDialogUpdates();
484
      diag.show( getSupportFragmentManager(), RubikDialogUpdates.getDialogTag() );
485
      }
486

    
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488

    
489
    public void onExit(View v)
490
      {
491
      RubikDialogExit diag = new RubikDialogExit();
492
      diag.show(getSupportFragmentManager(), null);
493
      }
494

    
495
///////////////////////////////////////////////////////////////////////////////////////////////////
496

    
497
    public void onAbout(View v)
498
      {
499
      RubikDialogAbout diag = new RubikDialogAbout();
500
      diag.show(getSupportFragmentManager(), null);
501
      }
502

    
503
///////////////////////////////////////////////////////////////////////////////////////////////////
504

    
505
    public void onBandage(View v)
506
      {
507
      RubikDialogCreators diag = new RubikDialogCreators();
508
      diag.show(getSupportFragmentManager(), RubikDialogCreators.getDialogTag() );
509
      }
510

    
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512

    
513
    public void receiveUpdate(RubikUpdates updates)
514
      {
515
      int num = updates.getCompletedNumber();
516
      updateBubble(num);
517
      }
518

    
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520

    
521
    public void objectDownloaded(String shortName)
522
      {
523
      mNumUpdates--;
524
      updateBubble(mNumUpdates);
525
      mGrid.updateGrid(this,mScreenWidth);
526
      }
527

    
528
///////////////////////////////////////////////////////////////////////////////////////////////////
529

    
530
    public int getType()
531
      {
532
      return 0;
533
      }
534

    
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536

    
537
    public void sortObjectsBy(int sortMode)
538
      {
539
      mSortMode = sortMode;
540
      mGrid.createGrid(this,mScreenWidth,mSortMode);
541
      }
542

    
543
///////////////////////////////////////////////////////////////////////////////////////////////////
544

    
545
    public void errorUpdate()
546
      {
547
      android.util.Log.e("D", "NewRubikActivity: Error receiving downloaded objects update");
548
      }
549
}
(1-1/4)