Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / MainActivity.java @ 58fd2ec0

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
      RubikScores scores = RubikScores.getInstance();
314
      scores.savePreferences(editor);
315

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

    
320
///////////////////////////////////////////////////////////////////////////////////////////////////
321

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

    
327
      RubikObjectList.restorePreferences(this,preferences,justStarted);
328
      RubikScores scores = RubikScores.getInstance();
329
      scores.restorePreferences(preferences);
330

    
331
      if( scores.isVerified() )
332
        {
333
        FirebaseAnalytics analytics = getAnalytics();
334
        analytics.setUserId(scores.getName());
335
        }
336
      }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339

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

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

    
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366
// PUBLIC API
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368

    
369
    public FirebaseAnalytics getAnalytics()
370
      {
371
      return mFirebaseAnalytics;
372
      }
373

    
374
///////////////////////////////////////////////////////////////////////////////////////////////////
375

    
376
    public int getObjectOrdinal()
377
      {
378
      return mCurrentObject;
379
      }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
    public void setCurrentObject(int current)
384
      {
385
      mCurrentObject = current;
386
      }
387

    
388
///////////////////////////////////////////////////////////////////////////////////////////////////
389

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

    
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398

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

    
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407

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

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

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

    
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425

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

    
433
///////////////////////////////////////////////////////////////////////////////////////////////////
434

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

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443

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

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

    
458
///////////////////////////////////////////////////////////////////////////////////////////////////
459

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

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

    
471
    public void onSettings(View v)
472
      {
473
      int sw = (int)(mScreenWidth*0.7);
474
      int sh = (int)(mScreenHeight*0.2f);
475

    
476
      int vw = v.getWidth();
477

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

    
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483

    
484
    public void onUpdates(View v)
485
      {
486
      RubikDialogUpdates diag = new RubikDialogUpdates();
487
      diag.show( getSupportFragmentManager(), RubikDialogUpdates.getDialogTag() );
488
      }
489

    
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491

    
492
    public void onExit(View v)
493
      {
494
      RubikDialogExit diag = new RubikDialogExit();
495
      diag.show(getSupportFragmentManager(), null);
496
      }
497

    
498
///////////////////////////////////////////////////////////////////////////////////////////////////
499

    
500
    public void onAbout(View v)
501
      {
502
      RubikDialogAbout diag = new RubikDialogAbout();
503
      diag.show(getSupportFragmentManager(), null);
504
      }
505

    
506
///////////////////////////////////////////////////////////////////////////////////////////////////
507

    
508
    public void onBandage(View v)
509
      {
510
      RubikDialogCreators diag = new RubikDialogCreators();
511
      diag.show(getSupportFragmentManager(), RubikDialogCreators.getDialogTag() );
512
      }
513

    
514
///////////////////////////////////////////////////////////////////////////////////////////////////
515

    
516
    public void receiveUpdate(RubikUpdates updates)
517
      {
518
      int num = updates.getCompletedNumber();
519
      updateBubble(num);
520
      }
521

    
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523

    
524
    public void objectDownloaded(String shortName)
525
      {
526
      mNumUpdates--;
527
      updateBubble(mNumUpdates);
528
      mGrid.updateGrid(this,mScreenWidth);
529
      }
530

    
531
///////////////////////////////////////////////////////////////////////////////////////////////////
532

    
533
    public int getType()
534
      {
535
      return 0;
536
      }
537

    
538
///////////////////////////////////////////////////////////////////////////////////////////////////
539

    
540
    public void sortObjectsBy(int sortMode)
541
      {
542
      mSortMode = sortMode;
543
      mGrid.createGrid(this,mScreenWidth,mSortMode);
544
      }
545

    
546
///////////////////////////////////////////////////////////////////////////////////////////////////
547

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